home *** CD-ROM | disk | FTP | other *** search
/ Scene Storm / Scene Storm - Volume 1.iso / coding / c / vbcc / machine.c < prev    next >
C/C++ Source or Header  |  1995-11-23  |  77KB  |  1,786 lines

  1. /*  File, das maschinenabhaengige Daten und Routinen fuer Codeerzeugung */
  2. /*  fuer Motorola 680x0-CPUs enthaelt (z.Z. auf 020+881 ausgerichtet).  */
  3.  
  4. #include "vbc.h"
  5.  
  6. /*  ab hier public Data, die vorhanden sein MUSS    */
  7.  
  8. char *ename[]={"strange","sequence","move","set+","set-","set*","set/","set%",
  9.                "set&","set^","set|","set<<","set>>","?:","lor","land","or",
  10.                "eor","and","equal","unequal","lt","le","gt","ge","lsl",
  11.                "lsr","add","sub","mul","div","mod","negate",
  12.                "not","preinc","postinc","predec","postdec","neg",
  13.                "dref-pointer","address-of","cast","call","index",
  14.                "dref-struct-pointer","dref-struct","identifier","constant",
  15.                "string","member",
  16.                 "convert-char","convert-short","convert-int","convert-long",
  17.                 "convert-float","convert-double","convert-void","convert-pointer",
  18.                 "convert-uchar","convert-ushort","convert-uint","convert-ulong",
  19.                 "address-of-array","first-element-of-array","pmult",
  20.                 "allocreg","freereg","pconstant","test","label","beq","bne",
  21.                 "blt","bge","ble","bgt","bra","compare","push","pop",
  22.                 "address-of-struct","add-int-to-pointer","sub-int-from-pointer",
  23.                 "sub-pointer-from-pointer","push-reg","pop-reg","pop-args",
  24.                 "save-regs","restore-regs","identifier-label","dc","align"};
  25.  
  26.  
  27. /*  Codegenerator-Flags                                 */
  28. int g_flags[MAXGF]={VALFLAG,VALFLAG,0,0,0,0,0,0,0,0};
  29. char *g_flags_name[MAXGF]={"cpu","fpu","d2scratch","noa4","sc","sd","prof","-","-","-"};
  30. union ppi g_flags_val[MAXGF];
  31.  
  32. /* Tabelle fuer alignment requirements, maschinenabhaengig */
  33. int align[]={1,1,2,2,2,2,2,2,2,2,2,2,2,2,2};
  34. int maxalign=2;
  35.  
  36. /*  Tabelle fuer die Groesse der einzelnen Typen    */
  37. int sizetab[]={0,1,2,4,4,4,8,0,4,0,0,0,4,0};
  38.  
  39. /*  Tabelle fuer minimale und maximale Werte der Integer-Typen  */
  40. zlong t_min[32];
  41. zulong t_max[32];
  42.  
  43. /*  Namen der Register              */
  44. char *regnames[MAXR+1]={"noreg","a0","a1","a2","a3","a4","a5","a6","a7",
  45.                                "d0","d1","d2","d3","d4","d5","d6","d7",
  46.                         "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7"};
  47.  
  48. /*  Anfangswerte fuer die Register  */
  49. int regsa[MAXR+1]={0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  50.  
  51. /*  Werden Register von Funktionen evtl. zerstoert? */
  52. int regscratch[MAXR+1]={0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0};
  53.  
  54. /*  Speicher fuer die Register      */
  55. int regs[MAXR+1];
  56.  
  57. /*  Merker, ob Register benutzt wurden  */
  58. int regused[MAXR+1];
  59.  
  60. /*  Variablen, die in Register liegen   */
  61. struct Var *regsv[MAXR+1];
  62.  
  63. extern int float_used;
  64.  
  65. /*  Ab hier private Data, speziell fuer einen Codegenerator */
  66.  
  67. char reglist[200];
  68.  
  69. #define DATA 0
  70. #define BSS 1
  71. #define CODE 2
  72.  
  73. int reglabel,freglabel,section=-1;
  74. char *codename,*bssname,*dataname;
  75.  
  76. struct IC *do_refs(FILE *,struct IC *);
  77. void pr(FILE *,struct IC *);
  78. int get_reg(FILE *,int,struct IC *);
  79. long pof2(zulong);
  80. void function_top(FILE *,struct Var *,int);
  81. void function_bottom(FILE *f,struct Var *,int);
  82.  
  83. void saverestoreregs(FILE *,int,int);
  84.  
  85. void assign(FILE *,struct IC *,struct obj *,struct obj *,int,int,int);
  86.  
  87. char x_s[]={'0','b','w','3','l'};
  88. char x_t[]={'?','b','w','l','l','s','d','v','l','a','s','u','e','f','?','?'};
  89.  
  90. char *quick[2]={"","q"};
  91. char *strshort[2]={"l","w"};
  92.  
  93. char *ubranch[]={"beq","bne","blo","bhs","bls","bhi"};
  94.  
  95. int pushedreg,stored_cc; /* pushedreg&2: aregsaved; 4: dreg; 8: freg */
  96.  
  97. #define D16OFF 1024
  98.  
  99. #ifndef SEEK_SET
  100. #define SEEK_SET 0
  101. #endif
  102.  
  103. int newobj=0;   /*  um zu erkennen, ob neue section erlaubt ist */
  104.  
  105. int init_cg(void)
  106. /*  Initialisiert evtl. maschinenspezifische Sachen, liefert 0, */
  107. /*  wenn etwas schiefgegangen ist                               */
  108. {
  109.     /*  default CPU ist 68000   */
  110.     if(!(g_flags[0]&USEDFLAG)) g_flags_val[0].l=68000;
  111.     /*  keine FPU per default   */
  112.     if(!(g_flags[1]&USEDFLAG)) g_flags_val[1].l=0;
  113.     if(g_flags_val[1].l<68000) {x_t[FLOAT]='l';}
  114.     /*  d2 als Scratchregister markeiren, wenn cclib benutzt wird   */
  115.     if(g_flags[2]&USEDFLAG) regscratch[11]=1;
  116.     /*  a4 als Scratchregister markeiren, wenn sclib benutzt wird   */
  117.     if(g_flags[3]&USEDFLAG) regsa[5]=1;
  118.     codename="\tsection\t\"CODE\",code\n";
  119.     /*  SmallData-Vorbereitungen    */
  120.     if(g_flags[5]&USEDFLAG){
  121.         regsa[5]=1;
  122.         bssname= "\tsection\t\"__MERGED\",bss\n";
  123.         dataname="\tsection\t\"__MERGED\",data\n";
  124.     }else{
  125.         bssname= "\tsection\t\"BSS\",bss\n";
  126.         dataname="\tsection\t\"DATA\",data\n";
  127.     }
  128.     /*  a5 zur Nutzung freigeben, wenn kein Framepointer benutzt wird   */
  129.     if(c_flags_val[0].l&256) regsa[6]=0;
  130.     if(DEBUG&1) printf("CPU=%ld FPU=%ld\n",g_flags_val[0].l,g_flags_val[1].l);
  131.     vlong=l2zl(0L);
  132.     t_min[UNSIGNED|CHAR]=t_min[UNSIGNED|SHORT]=t_min[UNSIGNED|INT]=t_min[UNSIGNED|LONG]=vlong;
  133.     vlong=l2zl((long)SCHAR_MIN); t_min[CHAR]=vlong;
  134.     vlong=l2zl((long)SHRT_MIN ); t_min[SHORT]=vlong;
  135.     vlong=l2zl((long)INT_MIN  ); t_min[INT]=vlong;
  136.     vlong=l2zl((long)LONG_MIN ); t_min[LONG]=vlong;
  137.     vulong=ul2zul((unsigned long)SCHAR_MAX); t_max[CHAR]=vulong;
  138.     vulong=ul2zul((unsigned long)SHRT_MAX ); t_max[SHORT]=vulong;
  139.     vulong=ul2zul((unsigned long)INT_MAX  ); t_max[INT]=vulong;
  140.     vulong=ul2zul((unsigned long)LONG_MAX ); t_max[LONG]=vulong;
  141.     vulong=ul2zul((unsigned long)UCHAR_MAX); t_max[UNSIGNED|CHAR]=vulong;
  142.     vulong=ul2zul((unsigned long)USHRT_MAX); t_max[UNSIGNED|SHORT]=vulong;
  143.     vulong=ul2zul((unsigned long)UINT_MAX ); t_max[UNSIGNED|INT]=vulong;
  144.     vulong=ul2zul((unsigned long)ULONG_MAX); t_max[UNSIGNED|LONG]=vulong;
  145.     return(1);
  146. }
  147.  
  148. int freturn(struct Typ *t)
  149. /*  Liefert Register zurueck, in dem Typ t von Funktionen zurueckgegeben    */
  150. /*  wird. Liefert Null, wenn Wert auf Stack zurueckgegeben wird.            */
  151. /*  Achtung! t kann pointer sein, aber trotzdem t->next==0!!                */
  152. /*  maschinenabhaengig                                                      */
  153. {
  154.     if((t->flags&15)==FLOAT)
  155.         {if(g_flags_val[1].l>=68000) return(17); else return(9);}
  156.     if((t->flags&15)==DOUBLE)
  157.         {if(g_flags_val[1].l>=68000) return(17); else return(0);}
  158.     if((t->flags&15)==STRUCT||(t->flags&15)==UNION) return(0);
  159.     if(szof(t)<=4) return(9); else return(0);
  160. }
  161.  
  162.  
  163. int regok(int r,int t,int mode)
  164. /*  Testet, ob Register r den Typ t verkraftet          */
  165. /*  mode!=0: mit Typ mode dereferenzierbar              */
  166. /*  natuerlich maschinenabhaengig                       */
  167. /*  Reg 1-8=a0-a7 9-16=d0-d7 und 17-24=FP0-FP7          */
  168. /*  dn nur Integers, an nur Pointer und FPn nur FK      */
  169. {
  170.     if(r==0) return(0);
  171.     t&=15;
  172.     if(t==FLOAT||t==DOUBLE){
  173.         if(g_flags_val[1].l>=68000){
  174.             if(r>=17&&r<=24) return(1); else return(0);
  175.         }else{
  176.             if(t==FLOAT&&r>=9&&r<=16) return(1); else return(0);
  177.         }
  178.     }
  179.     if(t==POINTER&&mode==0&&r>=9&&r<=16) return(1);
  180.     if(t==POINTER&&r>=1&&r<=8) return(1);
  181.     if(t>=CHAR&&t<=LONG&&r>=9&&r<=16) return(1);
  182.     return(0);
  183. }
  184.  
  185. int isquickkonst(union atyps *,int),isquickkonst2(union atyps *,int),regavailable(int);
  186. void move(FILE *,struct obj *,int,struct obj *,int,int);
  187. void add(FILE *,struct obj *,int,struct obj *,int,int);
  188. void sub(FILE *,struct obj *,int,struct obj *,int,int);
  189. void mult(FILE *,struct obj *,int,struct obj *,int,int,int,struct IC *);
  190.  
  191. long pof2(zulong x)
  192. /*  gibt log2(x)+1 oder 0 zurueck */
  193. {
  194.     zulong p;int ln=1;
  195.     p=ul2zul(1L);
  196.     while(zulleq(p,x)){
  197.         if(zuleqto(x,p)) return(ln);
  198.         ln++;p=zuladd(p,p);
  199.     }
  200.     return(0);
  201. }
  202.  
  203. #define isreg(x) ((p->x.flags&(REG|DREFOBJ))==REG)
  204.  
  205. int addressing(void);
  206. long notpopped,stackoffset,loff;
  207. int offlabel;
  208.  
  209. void gen_code(FILE *f,struct IC *p,struct Var *v,int offset)
  210. /*  Eigentliche gen_code()-Routine                          */
  211. {
  212.     int c,t,comptyp;char *fp="\0\0";
  213.     if(DEBUG&1) printf("gen_code()\n");
  214.     for(c=1;c<=MAXR;c++) regs[c]=regsa[c];
  215.     if(c_flags_val[0].l&128){
  216.     /*  Adressierungsarten benutzen */
  217.         if(!addressing()) offset=0;
  218.     }
  219.     reglabel=++label;freglabel=++label;
  220.     function_top(f,v,offset);
  221.     if(p!=first_ic) ierror(0);
  222.     for(;p;pr(f,p),p=p->next){
  223.         c=p->code;t=p->typf;pushedreg=0;
  224.         if(DEBUG&256) pric2(stdout,p);
  225.         if(DEBUG&512) fprintf(f,"; stackoffset=%ld, notpopped=%ld\n",stackoffset,notpopped);
  226.         if(notpopped&&(c==LABEL||c==COMPARE||c==TEST||c==BRA)){
  227.             fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[notpopped<=8],strshort[notpopped<32768],notpopped);
  228.             stackoffset-=notpopped;notpopped=0;
  229.         }
  230.         /*  na, ob das hier ok ist..?   */
  231.         if(c==SUBPFP) c=SUB;
  232.         if(c==PMULT) c=MULT;
  233.         if(c==ALLOCREG) {regs[p->q1.reg]=1;continue;}
  234.         if(c==FREEREG) {regs[p->q1.reg]=0;continue;}
  235.         if(c==LABEL) {fprintf(f,"l%d\n",t);continue;}
  236.         if(c==BRA){fprintf(f,"\tbra\tl%d\n",t);continue;}
  237.         if(c>=BEQ&&c<BRA){
  238.             if(stored_cc){fprintf(f,"\tbne\tl%d\n",t);stored_cc=0;continue;}
  239.             if((comptyp&UNSIGNED)||(comptyp&15)==POINTER){
  240.                 fprintf(f,"\t%s\tl%d\n",ubranch[c-BEQ],t);
  241.             }else{
  242.                 fprintf(f,"\t%s%s\tl%d\n",fp,ename[c],t);
  243.             }
  244.             continue;
  245.         }
  246.         if(p->q1.am){
  247.             if(!regs[p->q1.am->basereg]) ierror(0);
  248.             if(p->q1.am->dreg&&!regs[p->q1.am->dreg&127]) {printf("Register %s:\n",regnames[p->q1.am->dreg&127]);ierror(0);}
  249.         }
  250.         if(p->q2.am){
  251.             if(!regs[p->q2.am->basereg]) ierror(0);
  252.             if(p->q2.am->dreg&&!regs[p->q2.am->dreg&127]) {printf("Register %s:\n",regnames[p->q2.am->dreg&127]);ierror(0);}
  253.         }
  254.         if(p->z.am){
  255.             if(!regs[p->z.am->basereg]) ierror(0);
  256.             if(p->z.am->dreg&&!regs[p->z.am->dreg&127]) {printf("Register %s:\n",regnames[p->z.am->dreg&127]);ierror(0);}
  257.         }
  258.         if((p->q1.flags®)&&!regs[p->q1.reg]){printf("Register %s:\n",regnames[p->q1.reg]);ierror(0);}
  259.         if((p->q2.flags®)&&!regs[p->q2.reg]){printf("Register %s:\n",regnames[p->q2.reg]);ierror(0);}
  260.         if((p->z.flags®)&&!regs[p->z.reg]){printf("Register %s:\n",regnames[p->z.reg]);ierror(0);}
  261.         if((p->q2.flags®)&&(p->z.flags®)&&p->q2.reg==p->z.reg){printf("Register %s:\n",regnames[p->q2.reg]);ierror(0);}
  262.         if((p->q2.flags&VAR)&&(p->z.flags&VAR)&&p->q2.v==p->z.v){printf("Var %s:\n",p->q2.v->identifier);ierror(0);}
  263.         if(c==PUSHREG){
  264.             if(p->q1.reg<17) {fprintf(f,"\tmove.l\t%s,-(a7)\n",regnames[p->q1.reg]);stackoffset-=4;}
  265.              else {fprintf(f,"\tfmove.x\t%s,-(a7)\n",regnames[p->q1.reg]);stackoffset+=12;}
  266.             continue;
  267.         }
  268.         if(c==POPREG){
  269.             if(p->z.reg<17) {fprintf(f,"\tmove.l\t(a7)+,%s\n",regnames[p->z.reg]);stackoffset+=4;}
  270.              else {fprintf(f,"\tfmove.x\t(a7)+,%s\n",regnames[p->z.reg]);stackoffset+=12;}
  271.             continue;
  272.         }
  273.         if(c==SAVEREGS||c==RESTOREREGS){
  274.             saverestoreregs(f,c,p->q1.reg);
  275.             continue;
  276.         }
  277.         if(!(c_flags_val[0].l&128))
  278.             if(p->q1.am||p->q2.am||p->z.am){
  279.                 ierror(0);
  280.                 p->q1.am=p->q2.am=p->z.am=0;
  281.             }
  282.         p=do_refs(f,p);
  283.         if(!(c_flags_val[0].l&128))
  284.             if(p->q1.am||p->q2.am||p->z.am){
  285.                 ierror(0);
  286.                 p->q1.am=p->q2.am=p->z.am=0;
  287.             }
  288.         if(c>=CONVCHAR&&c<=CONVULONG){
  289.             int to;
  290.             if(c==CONVCHAR) to=CHAR;
  291.             if(c==CONVUCHAR) to=UNSIGNED|CHAR;
  292.             if(c==CONVSHORT) to=SHORT;
  293.             if(c==CONVUSHORT) to=UNSIGNED|SHORT;
  294.             if(c==CONVINT) to=LONG;
  295.             if(c==CONVUINT) to=UNSIGNED|LONG;
  296.             if(c==CONVLONG) to=LONG;
  297.             if(c==CONVULONG) to=UNSIGNED|LONG;
  298.             if(c==CONVFLOAT) to=FLOAT;
  299.             if(c==CONVDOUBLE) to=DOUBLE;
  300.             if(c==CONVPOINTER) to=UNSIGNED|LONG;
  301.             if(c==CONVVOID){ierror(0);continue;}
  302.             if(t==FLOAT||t==DOUBLE||to==FLOAT||to==DOUBLE){
  303.                 if(g_flags_val[1].l>=68000){
  304.                     int zreg=0;
  305.                     if((t==FLOAT||t==DOUBLE)&&(to==FLOAT||to==DOUBLE)){
  306.                         if(isreg(q1)&&isreg(z)){
  307.                             if(p->q1.reg!=p->z.reg)
  308.                                 fprintf(f,"\tfmove.x\t%s,%s\n",regnames[p->q1.reg],regnames[p->z.reg]);
  309.                             continue;
  310.                         }
  311.                     }
  312.                     if(isreg(z)&&p->z.reg>=17)
  313.                         zreg=p->z.reg;
  314.                     if(isreg(q1)&&p->q1.reg>=17){
  315.                         if(!zreg) zreg=p->q1.reg; else zreg=get_reg(f,2,p);}
  316.                     if(!zreg) zreg=get_reg(f,2,p);
  317.                     if((to&UNSIGNED)&&x_t[to&15]!='l'){
  318.                         int dreg=get_reg(f,1,p);
  319.                         fprintf(f,"\tmoveq\t#0,%s\n",regnames[dreg]);
  320.                         move(f,&p->q1,0,0,dreg,to);
  321.                         move(f,0,dreg,0,zreg,LONG);
  322.                     }else{
  323.                         if(!isreg(q1)||p->q1.reg!=zreg)
  324.                             move(f,&p->q1,0,0,zreg,to);
  325.                     }
  326.                     if(t!=FLOAT&&t!=DOUBLE){
  327.                     /*  nach integer, d.h. Kommastellen abschneiden */
  328.                         if(g_flags_val[1].l==68040||g_flags_val[1].l==68060){
  329.                         /*  bei 040/060 emuliert    */
  330.                             int dreg1=get_reg(f,1,p),dreg2=get_reg(f,1,p);
  331.                             fprintf(f,"\tfmove.l\tfpcr,%s\n",regnames[dreg2]);
  332.                             fprintf(f,"\tmoveq\t#16,%s\n",regnames[dreg1]);
  333.                             fprintf(f,"\tor.l\t%s,%s\n",regnames[dreg2],regnames[dreg1]);
  334.                             fprintf(f,"\tand.w\t#-33,%s\n",regnames[dreg1]);
  335.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg1]);
  336.                             fprintf(f,"\tfmove.%c\t%s,",x_t[t&15],regnames[zreg]);
  337.                             probj(f,&p->z,t,0);fprintf(f,"\n");
  338.                             fprintf(f,"\tfmove.l\t%s,fpcr\n",regnames[dreg2]);
  339.                             continue;
  340.                         }else{
  341.                             if(!isreg(q1)||p->q1.reg!=zreg){
  342.                                 fprintf(f,"\tfintrz\t%s\n",regnames[zreg]);
  343.                             }else{
  344.                                 int nreg=get_reg(f,2,p);
  345.                                 fprintf(f,"\tfintrz\t%s,%s\n",regnames[zreg],regnames[nreg]);
  346.                                 zreg=nreg;
  347.                             }
  348.                         }
  349.                     }
  350.                     if(to&UNSIGNED&&x_t[to&15]=='l'){
  351.                         int nlabel;
  352.                         fprintf(f,"\ttst.%c\t",x_t[to&15]);
  353.                         probj(f,&p->q1,to,0);fprintf(f,"\n");
  354.                         nlabel=++label;
  355.                         fprintf(f,"\tbge\tl%d\n",nlabel);
  356.                         fprintf(f,"\tfadd.d\t#4294967296,%s\n",regnames[zreg]);
  357.                         fprintf(f,"l%d\n",nlabel);
  358.                     }
  359.                     if(!(p->z.reg)||p->z.reg!=zreg){
  360.                         move(f,0,zreg,&p->z,0,t);
  361.                     }
  362.                 }else{
  363.                     if(to==t){
  364.                         assign(f,p,&p->q1,&p->z,ASSIGN,p->q2.reg,t);
  365.                         continue;
  366.                     }
  367.                     if(to==FLOAT&&t==DOUBLE){
  368.                         saverestoreregs(f,SAVEREGS,0); /* kein Zielregister */
  369.                         assign(f,p,&p->q1,0,PUSH,sizetab[FLOAT],FLOAT);
  370.                         fprintf(f,"\tpublic\t__ieees2d\n\tjsr\t__ieees2d\n\taddq.w\t#4,a7\n");
  371.                         stackoffset+=4;
  372.                         fprintf(f,"\tmovem.l\td0/d1,");
  373.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  374.                         saverestoreregs(f,RESTOREREGS,0);
  375.                         continue;
  376.                     }
  377.                     if(to==DOUBLE&&t==FLOAT){
  378.                         saverestoreregs(f,SAVEREGS,p->z.reg);
  379.                         assign(f,p,&p->q1,0,PUSH,sizetab[DOUBLE],DOUBLE);
  380.                         fprintf(f,"\tpublic\t__ieeed2s\n\tjsr\t__ieeed2s\n\taddq.w\t#8,a7\n");
  381.                         stackoffset+=8;
  382.                         move(f,0,9,&p->z,0,t);
  383.                         saverestoreregs(f,RESTOREREGS,p->z.reg);
  384.                         continue;
  385.                     }
  386.                     if(to==FLOAT||to==DOUBLE){
  387.                         saverestoreregs(f,SAVEREGS,p->z.reg);
  388.                         assign(f,p,&p->q1,0,PUSH,sizetab[to&15],to);
  389.                         fprintf(f,"\tpublic\t__ieeefix%c\n\tjsr\t__ieeefix%c\n\taddq.w\t#%d,a7\n",x_t[to&15],x_t[to&15],sizetab[to&15]);
  390.                         stackoffset+=sizetab[to&15];
  391.                         move(f,0,9,&p->z,0,t);
  392.                         saverestoreregs(f,RESTOREREGS,p->z.reg);
  393.                         continue;
  394.                     }else{
  395.                         int uns,xt=x_t[to&15];
  396.                         if(to&UNSIGNED) uns='u'; else uns='s';
  397.                         saverestoreregs(f,SAVEREGS,p->z.reg);
  398.                         if(xt!='l') {fprintf(f,"\tsubq.w\t#4,a7\n");stackoffset-=4;}
  399.                         fprintf(f,"\tmove.%c\t",xt);
  400.                         probj(f,&p->q1,to,0);
  401.                         if(xt!='l') fprintf(f,",(a7)\n"); else {fprintf(f,",-(a7)\n");stackoffset-=4;}
  402.                         fprintf(f,"\tpublic\t__ieeeflt%c%c%c\n\tjsr\t__ieeeflt%c%c%c\n\taddq.w\t#4,a7\n",uns,xt,x_t[t&15],uns,xt,x_t[t&15]);
  403.                         stackoffset+=4;
  404.                         if(t==DOUBLE){
  405.                             fprintf(f,"\tmovem.l\td0/d1,");
  406.                             probj(f,&p->z,t,0);fprintf(f,"\n");
  407.                         }else move(f,0,9,&p->z,0,t);
  408.                         saverestoreregs(f,RESTOREREGS,p->z.reg);
  409.                         continue;
  410.                     }
  411.                 }
  412.                 continue;
  413.             }
  414.             if((to&15)<(t&15)){
  415.                 int zreg;
  416.                 if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16)
  417.                     zreg=p->z.reg; else zreg=get_reg(f,1,p);
  418.                 /*  aufpassen, falls unsigned und Quelle==Ziel  */
  419.                 if((to&UNSIGNED)&&isreg(q1)&&zreg==p->q1.reg){
  420.                     unsigned long l;
  421.                     if((to&15)==CHAR) l=0xff; else l=0xffff;
  422.                     fprintf(f,"\tand.%c\t#%lu,%s\n",x_t[t&15],l,regnames[zreg]);
  423.                     continue;
  424.                 }
  425.                 if(to&UNSIGNED) fprintf(f,"\tmoveq\t#0,%s\n",regnames[zreg]);
  426.                 move(f,&p->q1,0,0,zreg,to);
  427.                 if(!(to&UNSIGNED)){
  428.                     if((to&15)==CHAR&&(t&15)==SHORT) fprintf(f,"\text.w\t%s\n",regnames[zreg]);
  429.                     if((to&15)==SHORT&&sizetab[t&15]==4) fprintf(f,"\text.l\t%s\n",regnames[zreg]);
  430.                     if((to&15)==CHAR&&sizetab[t&15]==4){
  431.                         if(g_flags_val[0].l>=68020)
  432.                             fprintf(f,"\textb.l\t%s\n",regnames[zreg]);
  433.                         else
  434.                             fprintf(f,"\text.w\t%s\n\text.l\t%s\n",regnames[zreg],regnames[zreg]);
  435.                     }
  436.                 }
  437.                 if(!isreg(z)||p->z.reg!=zreg){
  438.                     move(f,0,zreg,&p->z,0,t);
  439.                 }
  440.             }else{
  441.                 long diff;int m;
  442.                 m=0;
  443.                 if(p->q1.flags®){
  444.                     p->q1.val.vlong=l2zl(0L);
  445.                     p->q1.flags|=D16OFF;m=1;
  446.                 }
  447.                 diff=sizetab[to&15]-sizetab[t&15];
  448.                 vlong=l2zl(diff);
  449.                 p->q1.val.vlong=zladd(p->q1.val.vlong,vlong);
  450.                 move(f,&p->q1,0,&p->z,0,t);
  451.                 vlong=l2zl(diff);
  452.                 p->q1.val.vlong=zlsub(p->q1.val.vlong,vlong);
  453.                 if(m) p->q1.flags&=~D16OFF;
  454.             }
  455.             continue;
  456.         }
  457.         if((t==FLOAT||t==DOUBLE)&&g_flags_val[1].l>=68000) *fp='f'; else *fp=0;
  458.         if(c==MINUS||c==KOMPLEMENT){
  459.             int zreg;
  460.             if(t==FLOAT||t==DOUBLE){
  461.                 if(g_flags_val[1].l>=68000){
  462.                     if(isreg(z)) zreg=p->z.reg; else zreg=get_reg(f,2,p);
  463.                     fprintf(f,"\tfneg.%c\t",x_t[t&15]);probj(f,&p->q1,t,0);
  464.                     fprintf(f,",%s\n",regnames[zreg]);
  465.                     if(!isreg(z)||p->z.reg!=zreg){
  466.                         move(f,0,zreg,&p->z,0,t);
  467.                     }
  468.                     continue;
  469.                 }else{
  470.                     saverestoreregs(f,SAVEREGS,p->z.reg);
  471.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  472.                     fprintf(f,"\tpublic\t__ieeeneg%c\n\tjsr\t__ieeeneg%c\n\taddq.w\t#%d,a7\n",x_t[t&15],x_t[t&15],sizetab[t&15]);
  473.                     stackoffset+=sizetab[t&15];
  474.                     if(t==DOUBLE){
  475.                         fprintf(f,"\tmovem.l\td0/d1,");
  476.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  477.                     }else move(f,0,9,&p->z,0,t);
  478.                     saverestoreregs(f,RESTOREREGS,p->z.reg);
  479.                     continue;
  480.                 }
  481.             }
  482.             if(p->q1.flags==p->z.flags){
  483.                 if(!(p->q1.flags&VAR)||(p->q1.v==p->z.v&&zleqto(p->q1.val.vlong,p->z.val.vlong))){
  484.                     if(!isreg(q1)||p->q1.reg==p->z.reg){
  485.                         fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  486.                         probj(f,&p->q1,t,0);fprintf(f,"\n");
  487.                         continue;
  488.                     }
  489.                 }
  490.             }
  491.             if(isreg(z)&&p->z.reg>=9/*&&p->z.reg<=16*/)
  492.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  493.             if(!isreg(q1)||p->q1.reg!=zreg){
  494.                 move(f,&p->q1,0,0,zreg,t);
  495.             }
  496.             fprintf(f,"\t%s.%c\t%s\n",ename[c],x_t[t&15],regnames[zreg]);
  497.             if(!isreg(z)||p->z.reg!=zreg){
  498.                 move(f,0,zreg,&p->z,0,t);
  499.             }
  500.             continue;
  501.         }
  502.         if(c==CALL){
  503.             fprintf(f,"\tjsr\t");probj(f,&p->q1,t,0);
  504.             fprintf(f,"\n");
  505.             if(p->q2.reg){
  506.                 if((c_flags_val[0].l&256)&&(pushedreg&14)){
  507.                 /*  Entfernen der Parameter verzoegern  */
  508.                     notpopped+=p->q2.reg;
  509.                 }else{
  510.                     fprintf(f,"\tadd%s.%s\t#%d,a7\n",quick[p->q2.reg<=8],strshort[p->q2.reg<32768],p->q2.reg);
  511.                     stackoffset+=p->q2.reg;
  512.                 }
  513.             }
  514.             continue;
  515.         }
  516.         /*  COMPARE #0 durch TEST ersetzen (erlaubt, da tst alle Flags setzt)   */
  517.         if(c==COMPARE&&(p->q2.flags&KONST)){
  518.             eval_const(&p->q2.val,t);
  519.             if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
  520.                 c=p->code=TEST;p->q2.flags=0;
  521.             }
  522.         }
  523.         if(c==COMPARE&&(p->q1.flags&KONST)){
  524.             eval_const(&p->q1.val,t);
  525.             if(zleq(vlong)&&zuleq(vulong)&&zdeq(vdouble)){
  526.                 c=p->code=TEST;p->q1=p->q2;p->q2.flags=0;
  527.             }
  528.         }
  529.         if(c==TEST){
  530.             comptyp=t;
  531.             if(g_flags_val[0].l<68020&&isreg(q1)&&p->q1.reg>=1&&p->q1.reg<=8){
  532.             /*  tst ax gibt es nicht bei <68000 :-( */
  533.                 if(regavailable(1)){
  534.                     fprintf(f,"\tmove.%c\t%s,%s\n",x_t[t&15],regnames[p->q1.reg],regnames[get_reg(f,1,p)]);
  535.                 }else{
  536.                     fprintf(f,"\tcmp.w\t#0,%s\n",regnames[p->q1.reg]);
  537.                 }
  538.                 continue;
  539.             }
  540.             if((t==DOUBLE||t==FLOAT)&&g_flags_val[1].l<68000){
  541.             /*  nicht sehr schoen   */
  542.                 int result=get_reg(f,1,p);
  543.                 saverestoreregs(f,SAVEREGS,result);
  544.                 assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  545.                 fprintf(f,"\tpublic\t__ieeetst%c\n\tjsr\t__ieeetst%c\n\taddq.w\t#%d,a7\n",x_t[t&15],x_t[t&15],sizetab[t&15]);
  546.                 stackoffset+=sizetab[t&15];
  547.                 if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  548.                 saverestoreregs(f,RESTOREREGS,result);
  549.                 fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  550.                 continue;
  551.             }
  552.             fprintf(f,"\t%stst.%c\t",fp,x_t[t&15]);probj(f,&p->q1,t,0);
  553.             fprintf(f,"\n");
  554.             continue;
  555.         }
  556.         if(c==ASSIGN||c==PUSH||c==POP){
  557.             assign(f,p,&p->q1,&p->z,c,p->q2.reg,t);
  558.             continue;
  559.         }
  560.         if(c==ADDRESS){
  561.             int zreg;
  562.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=8)
  563.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  564.             fprintf(f,"\tlea\t");probj(f,&p->q1,t,0);
  565.             fprintf(f,",%s\n",regnames[zreg]);
  566.             if(!isreg(z)||p->z.reg!=zreg){
  567.                 move(f,0,zreg,&p->z,0,POINTER);
  568.             }
  569.             continue;
  570.         }
  571.         if(c==COMPARE){
  572.             int zreg;
  573.             comptyp=t;
  574.             if((p->q1.flags&KONST)||isreg(q2)){
  575.             /*  evtl. Argumente von cmp und nachfolgendes bcc umdrehen  */
  576.                 struct IC *n;struct obj m;
  577.                 n=p->next;
  578.                 while(n){
  579.                     if(n->code>=BEQ&&n->code<BRA){
  580.                         if(!p->z.flags){
  581.                             if(DEBUG&1) printf("arguments of cmp exchanged\n");
  582.                             m=p->q1;p->q1=p->q2;p->q2=m;
  583.                             p->z.flags=1;
  584.                         }
  585.                         /*  nachfolgenden Branch umdrehen   */
  586.                         switch(n->code){
  587.                             case BGT: n->code=BLT;break;
  588.                             case BLT: n->code=BGT;break;
  589.                             case BGE: n->code=BLE;break;
  590.                             case BLE: n->code=BGE;break;
  591.                         }
  592.                         break;
  593.                     }
  594.                     if(n->code==FREEREG) n=n->next; else{ierror(0); break;}
  595.                 }
  596.             }
  597.             if(t==FLOAT||t==DOUBLE){
  598.                 if(g_flags_val[1].l>=68000){
  599.                     if(isreg(q1)&&p->q1.reg>=17){
  600.                         zreg=p->q1.reg;
  601.                     }else{
  602.                         zreg=get_reg(f,2,p);
  603.                         move(f,&p->q1,0,0,zreg,t);
  604.                     }
  605.                     fprintf(f,"\tfcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  606.                     fprintf(f,",%s\n",regnames[zreg]);
  607.                     continue;
  608.                 }else{
  609.                 /*  nicht sehr schoen   */
  610.                     int result=get_reg(f,1,p);
  611.                     saverestoreregs(f,SAVEREGS,result);
  612.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  613.                     assign(f,p,&p->q2,0,PUSH,sizetab[t&15],t);
  614.                     fprintf(f,"\tpublic\t__ieeecmp%c\n\tjsr\t__ieeecmp%c\n\tadd.w\t#%d,a7\n",x_t[t&15],x_t[t&15],2*sizetab[t&15]);
  615.                     stackoffset+=2*sizetab[t&15];
  616.                     if(result!=9) fprintf(f,"\tmove.l\td0,%s\n",regnames[result]);
  617.                     saverestoreregs(f,RESTOREREGS,result);
  618.                     fprintf(f,"\ttst.l\t%s\n",regnames[result]);
  619.                     continue;
  620.                 }
  621.             }
  622.             if(p->q2.flags&KONST){
  623.                 fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  624.                 fprintf(f,",");probj(f,&p->q1,t,0);fprintf(f,"\n");
  625.                 continue;
  626.             }
  627.             if(isreg(q1)){
  628.                 zreg=p->q1.reg;
  629.             }else{
  630.                 zreg=get_reg(f,1,p);    /* hier evtl. auch Adressregister nehmen */
  631.                 move(f,&p->q1,0,0,zreg,t);
  632.             }
  633.             fprintf(f,"\tcmp.%c\t",x_t[t&15]);probj(f,&p->q2,t,0);
  634.             fprintf(f,",%s\n",regnames[zreg]);
  635.             continue;
  636.         }
  637.         if(c==ADDI2P||c==SUBIFP){
  638.             int zreg;
  639.             if(((p->q1.flags&VAR)&&(p->z.flags&VAR)&&p->q1.v==p->z.v)||
  640.                (isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg)){
  641.                 int r;
  642.                 if(p->q2.flags&KONST){
  643.                     if(c==ADDI2P)
  644.                         fprintf(f,"\tadd%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  645.                     else
  646.                         fprintf(f,"\tsub%s.l\t",quick[isquickkonst2(&p->q2.val,t)]);
  647.                     probj(f,&p->q2,t,0);fprintf(f,",");
  648.                     probj(f,&p->z,POINTER,0);fprintf(f,"\n");
  649.                     continue;
  650.                 }
  651.                 if(isreg(q2)&&p->q2.reg>=1){
  652.                     r=p->q2.reg;
  653.                 }else{
  654.                     r=get_reg(f,1,p);
  655.                     move(f,&p->q2,0,0,r,t);
  656.                 }
  657.                 if(x_t[t&15]!='l'&&(!isreg(z)||p->z.reg<1||p->z.reg>8)){
  658.                 /*  wenn Ziel kein Adressregister, muss short erst auf long */
  659.                 /*  char darf hier nicht auftreteten und long passt schon   */
  660.                     if(t&UNSIGNED) fprintf(f,"\tswap\t%s\n\tclr.w\t%s\n\tswap\t%s\n",regnames[r],regnames[r],regnames[r]);
  661.                      else          fprintf(f,"\text.l\t%s\n",regnames[r]);
  662.                     t=POINTER;
  663.                 }
  664. /*                if(c==ADDI2P)
  665.                     fprintf(f,"\tadd.%c\t%s,",x_t[t&15],regnames[r]);
  666.                 else
  667.                     fprintf(f,"\tsub.%c\t%s,",x_t[t&15],regnames[r]);
  668.                 probj(f,&p->z,t,0);fprintf(f,"\n");*/
  669.                 if(c==ADDI2P) add(f,0,r,&p->z,0,t);
  670.                  else         sub(f,0,r,&p->z,0,t);
  671.                 continue;
  672.             }
  673.             if(isreg(z)&&p->z.reg>=1&&p->z.reg<=16)
  674.                 zreg=p->z.reg; else zreg=get_reg(f,0,p);
  675.             if(!isreg(q1)||p->q1.reg!=zreg){
  676.                 move(f,&p->q1,0,0,zreg,POINTER);
  677.             }
  678.             if(c==ADDI2P) add(f,&p->q2,0,0,zreg,t);
  679.              else         sub(f,&p->q2,0,0,zreg,t);
  680.             if(!isreg(z)||p->z.reg!=zreg){
  681.                 move(f,0,zreg,&p->z,0,POINTER);
  682.             }
  683.             continue;
  684.         }
  685.         if((c>=OR&&c<=AND)||(c>=LSHIFT&&c<=MOD)){
  686.             int zreg,q1reg,q2reg,divflag=0;
  687.             if(t==FLOAT||t==DOUBLE){
  688.                 if(g_flags_val[1].l>=68000){
  689.                     if(isreg(z)&&p->z.reg>=17) zreg=p->z.reg;
  690.                         else zreg=get_reg(f,2,p);
  691.                     if(!isreg(q1)||p->q1.reg!=p->z.reg)
  692.                         move(f,&p->q1,0,0,zreg,t);
  693.                     fprintf(f,"\tf%s.%c\t",ename[c],x_t[t&15]);probj(f,&p->q2,t,0);
  694.                     fprintf(f,",%s\n",regnames[zreg]);
  695.                     if(!isreg(z)||p->z.reg!=zreg){
  696.                         move(f,0,zreg,&p->z,0,t);
  697.                     }
  698.                     continue;
  699.                 }else{
  700.                     saverestoreregs(f,SAVEREGS,p->z.reg);
  701.                     assign(f,p,&p->q1,0,PUSH,sizetab[t&15],t);
  702.                     assign(f,p,&p->q2,0,PUSH,sizetab[t&15],t);
  703.                     fprintf(f,"\tpublic\t__ieee%s%c\n\tjsr\t__ieee%s%c\n\tadd.w\t#%d,a7\n",ename[c],x_t[t&15],ename[c],x_t[t&15],2*sizetab[t&15]);
  704.                     stackoffset+=2*sizetab[t&15];
  705.                     if(t==DOUBLE){
  706.                         fprintf(f,"\tmovem.l\td0/d1,");
  707.                         probj(f,&p->z,0,t);fprintf(f,"\n");
  708.                     }else move(f,0,9,&p->z,0,t);
  709.                     saverestoreregs(f,RESTOREREGS,p->z.reg);
  710.                     continue;
  711.                 }
  712.             }
  713.             if((c==MULT||c==DIV||(c==MOD&&(p->typf&UNSIGNED)))&&(p->q2.flags&KONST)){
  714.             /*  ersetzt mul etc. mit Zweierpotenzen     */
  715.             /*  hier evtl. noch Fehler                  */
  716.                 long ln;zlong zl;
  717.                 eval_const(&p->q2.val,t&31);
  718.                 zl=l2zl(0L);
  719.                 if(zlleq(zl,vlong)&&zulleq(zl,vulong)){
  720.                     if(ln=pof2(vulong)){
  721.                         if(c==MOD){
  722.                             zl=l2zl(1L);
  723.                             vlong=zlsub(vlong,zl);
  724.                             p->code=AND;
  725.                         }else{
  726.                             vlong=l2zl(ln-1);
  727.                             if(c==DIV) {divflag=1;p->code=RSHIFT;} else p->code=LSHIFT;
  728.                         }
  729.                         c=p->code;
  730.                         if((t&31)==CHAR) p->q2.val.vchar=zl2zc(vlong);
  731.                         if((t&31)==SHORT) p->q2.val.vshort=zl2zs(vlong);
  732.                         if((t&31)==INT) p->q2.val.vint=zl2zi(vlong);
  733.                         if((t&31)==LONG) p->q2.val.vlong=vlong;
  734.                         vulong=zl2zul(vlong);
  735.                         if((t&31)==(UNSIGNED|CHAR)) p->q2.val.vuchar=zul2zuc(vulong);
  736.                         if((t&31)==(UNSIGNED|SHORT)) p->q2.val.vushort=zul2zus(vulong);
  737.                         if((t&31)==(UNSIGNED|INT))  p->q2.val.vuint=zul2zui(vulong);
  738.                         if((t&31)==(UNSIGNED|LONG)) p->q2.val.vulong=vulong;
  739.                     }
  740.                 }
  741.             }
  742.             if(c==DIV||c==MOD){
  743.                 if(x_t[t&15]=='l'&&g_flags_val[0].l<68020){
  744.                 /*  das hier ist auch nicht allzu schoen  */
  745.                     char *fname;
  746.                     saverestoreregs(f,SAVEREGS,p->z.reg);
  747.                     fprintf(f,"\tmove.l\t"); probj(f,&p->q2,t,0);
  748.                     fprintf(f,",-(a7)\n");
  749.                     stackoffset-=4;
  750.                     fprintf(f,"\tmove.l\t"); probj(f,&p->q1,t,0);
  751.                     fprintf(f,",-(a7)\n");
  752.                     stackoffset-=4;
  753.                     if(c==DIV){
  754.                         if(t&UNSIGNED) fname="divu"; else fname="divs";
  755.                     }else{
  756.                         if(t&UNSIGNED) fname="modu"; else fname="mods";
  757.                     }
  758.                     fprintf(f,"\tpublic\t__l%s\n",fname);
  759.                     fprintf(f,"\tjsr\t__l%s\n",fname);
  760.                     fprintf(f,"\taddq.w\t#8,a7\n");
  761.                     stackoffset+=8;
  762.                     move(f,0,9,&p->z,0,t);
  763.                     saverestoreregs(f,RESTOREREGS,p->z.reg);
  764.                     continue;
  765.                 }
  766.  
  767.             }
  768.             /*  hier die zweite Alternative mit isreg() schreiben?  */
  769.             if(((p->q2.flags&VAR)&&(p->z.flags&VAR)&&p->q2.v==p->z.v)||(p->q2.reg!=0&&p->q2.reg==p->z.reg)){
  770.                 struct obj m;
  771.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  772.                     if(c!=SUB){
  773.                         m=p->q1;p->q1=p->q2;p->q2=m;
  774.                     }else{
  775.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  776.                             m=p->q1;p->q1=p->q2;p->q2=m;
  777.                             c=ADD;
  778.                             fprintf(f,"\tneg.%c\t",x_t[t&15]);
  779.                             probj(f,&p->q1,t,0);fprintf(f,"\n");
  780.                         }
  781.                     }
  782.                 }
  783.             }
  784.             if(((p->q1.flags&VAR)&&p->z.flags==p->q1.flags&&p->q1.v==p->z.v&&zleqto(p->q1.val.vlong,p->z.val.vlong))||
  785.                (isreg(q1)&&isreg(z)&&p->q1.reg==p->z.reg)){
  786.                 if((c>=OR&&c<=AND)||c==ADD||c==SUB){
  787.                     int r;
  788.                     if(p->q2.flags&KONST){
  789.                         if(c==ADD) {add(f,&p->q2,0,&p->z,0,t);continue;}
  790.                         if(c==SUB) {sub(f,&p->q2,0,&p->z,0,t);continue;}
  791.                         fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  792.                         probj(f,&p->q2,t,0);fprintf(f,",");
  793.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  794.                         continue;
  795.                     }
  796.                     if(!isreg(z)){
  797.                         if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16)
  798.                             r=p->q2.reg; else r=get_reg(f,1,p);
  799.                         if(!isreg(q2)||p->q2.reg!=r){
  800.                             move(f,&p->q2,0,0,r,t);
  801.                         }
  802.                         fprintf(f,"\t%s.%c\t%s,",ename[c],x_t[t&15],regnames[r]);
  803.                         probj(f,&p->z,t,0);fprintf(f,"\n");
  804.                         continue;
  805.                     }
  806.                 }
  807.             }
  808.             /*  bei xor oder asl (ausser 0<=const<=8) muss q2 in Register   */
  809.             if(isreg(q2)&&p->q2.reg>=9&&p->q2.reg<=16){
  810.                 q2reg=p->q2.reg;
  811.             }else{
  812.                 if(c==LSHIFT||c==RSHIFT||c==XOR){
  813.                     eval_const(&p->q2.val,t&31);
  814.                     if(c==XOR||!(p->q2.flags&KONST)||!isquickkonst2(&p->q2.val,t)){
  815.                         q2reg=get_reg(f,1,p);
  816.                         move(f,&p->q2,0,0,q2reg,t);
  817.                     }else q2reg=0;
  818.                 }else{
  819.                     q2reg=0;
  820.                 }
  821.             }
  822.             if(isreg(z)&&p->z.reg>=9&&p->z.reg<=16&&p->z.reg!=q2reg)
  823.                 zreg=p->z.reg; else zreg=get_reg(f,1,p);
  824.             if(isreg(q1)&&p->q1.reg>=9&&p->q1.reg<=16)
  825.                 q1reg=p->q1.reg; else q1reg=0;
  826.             if(q1reg!=zreg){
  827.                 move(f,&p->q1,0,0,zreg,t);
  828.             }
  829.             if(c!=MULT&&c!=DIV&&c!=MOD&&c!=ADD&&c!=SUB){
  830.                 if(c==RSHIFT&&divflag&&!(t&UNSIGNED)) fprintf(f,"\tasr.%c\t",x_t[t&15]);
  831.                  else fprintf(f,"\t%s.%c\t",ename[c],x_t[t&15]);
  832.                 if(q2reg) fprintf(f,"%s",regnames[q2reg]); else probj(f,&p->q2,t,0);
  833.                 fprintf(f,",%s\n",regnames[zreg]);
  834.             }else{
  835.                 if(c==ADD) add(f,&p->q2,q2reg,0,zreg,t);
  836.                 if(c==SUB) sub(f,&p->q2,q2reg,0,zreg,t);
  837.                 if(c==MULT||c==DIV||c==MOD) mult(f,&p->q2,q2reg,0,zreg,t,c,p);
  838.             }
  839.             if((!isreg(z)||p->z.reg!=zreg)){
  840.                 move(f,0,zreg,&p->z,0,t);
  841.             }
  842.             continue;
  843.         }
  844.         ierror(0);
  845.     }
  846.     function_bottom(f,v,offset);
  847. }
  848. int get_reg(FILE *f,int flag,struct IC *p)
  849. /*  Besorgt Register flag=0=areg, 1=dreg, 2=fpreg           */
  850. {
  851.     int i;
  852.     flag=1+flag*8;
  853.     for(i=flag;i<flag+8;i++){
  854.         if(regs[i]==0){
  855.             if(p){
  856.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  857.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  858.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  859. /*                    iwarning("%s used in get_reg(1)",regnames[i]);*/
  860.                     continue;
  861.                 }
  862.             }
  863.             regs[i]=2;pushedreg|=1;
  864.             if(!regused[i]&&!regscratch[i]){regused[i]=1; }
  865.             return(i);
  866.         }
  867.     }
  868.     for(i=flag;i<flag+8;i++){
  869.         if(regs[i]==1&&(!p||(i!=p->q1.reg&&i!=p->q2.reg&&i!=p->z.reg))){
  870.             if(p){
  871.                 if((p->q1.am&&(p->q1.am->dreg==i||p->q1.am->basereg==i))
  872.                  ||(p->q2.am&&(p->q2.am->dreg==i||p->q2.am->basereg==i))
  873.                  ||(p->z.am&&(p->z.am->dreg==i||p->z.am->basereg==i))){
  874. /*                    iwarning("%s used in get_reg(2)",regnames[i]);*/
  875.                     continue;
  876.                 }
  877.             }
  878.  
  879.             regs[i]+=4;
  880.             if(i<17) {fprintf(f,"\tmove.l\t%s,-(a7)\n",regnames[i]);stackoffset-=4;}
  881.              else {fprintf(f,"\tfmove.x\t%s,-(a7)\n",regnames[i]);stackoffset-=12;}
  882. /*            if(p->code==COMPARE) ierror("corrupt code for compare generated - sorry");*/
  883.             if(i<9) pushedreg|=2;
  884.             else if (i<17) pushedreg|=4;
  885.             else pushedreg|=8;
  886.             return(i);
  887.         }
  888.     }
  889.     ierror(0);
  890.     for(i=flag;i<flag+8;i++) printf("%s: %d\n",regnames[i],regs[i]);
  891.     return(0);
  892. }
  893.  
  894. int isquickkonst(union atyps *p,int t)
  895. /*  liefert 1, wenn p auf Konstante zwischen -128 und 127 ist   */
  896. {
  897.     zlong zl;zulong zul;
  898.     eval_const(p,t);
  899.     if(t&UNSIGNED){
  900.         zul=ul2zul(127UL);
  901.         return(zulleq(vulong,zul));
  902.     }else{
  903.         zl=l2zl(-129L);
  904.         if(zlleq(vlong,zl)) return(0);
  905.         zl=l2zl(127L);
  906.         return(zlleq(vlong,zl));
  907.     }
  908. }
  909. int isquickkonst2(union atyps *p,int t)
  910. /*  liefert 1, wenn p auf Konstante zwischen 0 und 8 ist   */
  911. {
  912.     zlong zl;zulong zul;
  913.     eval_const(p,t);
  914.     if(t&UNSIGNED){
  915.         zul=ul2zul(8UL);
  916.         return(zulleq(vulong,zul));
  917.     }else{
  918.         zl=l2zl(-1L);
  919.         if(zlleq(vlong,zl)) return(0);
  920.         zl=l2zl(8L);
  921.         return(zlleq(vlong,zl));
  922.     }
  923. }
  924. int regavailable(int art)
  925. /*  liefert true, wenn Register mit art frei ist, sonst 0       */
  926. {
  927.     int i;
  928.     art=1+art*8;
  929.     for(i=art+1;i<art+8;i++)
  930.         if(regs[i]==0) return(1);
  931.     return(0);
  932. }
  933.  
  934. int compare_objects(struct obj *o1,struct obj *o2)
  935. /*  Vergleicht, ob die beiden Objekte fuer d0_refs gleich sind  */
  936. {
  937.     if(o1->flags==o2->flags){
  938.         if(!(o1->flags&VAR)||(o1->v==o2->v&&zleqto(o1->val.vlong,o2->val.vlong))){
  939.             if(!(o1->flags®)||o1->reg==o2->reg){
  940.                 return(1);
  941.             }
  942.         }
  943.     }
  944.     return(0);
  945. }
  946.  
  947. struct IC *do_refs(FILE *f,struct IC *p)
  948. /*  Kopiert DREFOBJs in Adressregister, wenn noetig         */
  949. /*  und kleine Konstanten in Datenregister                  */
  950. /*  zerstoert die ICs dabei so, dass kein zweiter Pass      */
  951. /*  moeglich ist (was aber durch reg/freg garantiert ist).  */
  952. {
  953.     int reg,c=p->code,t=p->typf,equal;
  954.     if((p->q1.flags&DREFOBJ)&&(!(p->q1.flags®)||p->q1.reg<1||p->q1.reg>8)){
  955.         equal=0;
  956.         if(compare_objects(&p->q1,&p->q2)) equal|=1;
  957.         if(compare_objects(&p->q1,&p->z)) equal|=2;
  958.         reg=get_reg(f,0,p);
  959.         p->q1.flags&=~DREFOBJ;
  960.         fprintf(f,"\tmove.l\t");probj(f,&p->q1,t,0);
  961.         p->q1.flags=REG|SCRATCH|DREFOBJ;
  962.         p->q1.reg=reg;
  963.         fprintf(f,",%s\n",regnames[p->q1.reg]);
  964.         if(equal&1) p->q2=p->q1;
  965.         if(equal&2) p->z=p->q1;
  966.     }
  967.     if((p->q2.flags&DREFOBJ)&&(!(p->q2.flags®)||p->q2.reg<1||p->q2.reg>8)){
  968.         if(compare_objects(&p->q2,&p->z)) equal=1; else equal=0;
  969.         reg=get_reg(f,0,p);
  970.         p->q2.flags&=~DREFOBJ;
  971.         fprintf(f,"\tmove.l\t");probj(f,&p->q2,t,0);
  972.         p->q2.flags=REG|SCRATCH|DREFOBJ;
  973.         p->q2.reg=reg;
  974.         fprintf(f,",%s\n",regnames[p->q2.reg]);
  975.         if(equal) p->z=p->q2;
  976.     }
  977.     if((p->z.flags&DREFOBJ)&&(!(p->z.flags®)||p->z.reg<1||p->z.reg>8)){
  978.         reg=get_reg(f,0,p);
  979.         p->z.flags&=~DREFOBJ;
  980.         fprintf(f,"\tmove.l\t");probj(f,&p->z,t,0);
  981.         p->z.flags=REG|SCRATCH|DREFOBJ;
  982.         p->z.reg=reg;
  983.         fprintf(f,",%s\n",regnames[p->z.reg]);
  984.     }
  985.  
  986.     if(x_t[t&15]=='l'&&(t&15)!=FLOAT&&(c!=ASSIGN||!isreg(z))&&c!=MULT&&c!=DIV&&c!=MOD&&c!=LSHIFT&&c!=RSHIFT){
  987.     /*  Konstanten evtl. in Register, noch nicht getestet   */
  988.         if((p->q1.flags&KONST)&&isquickkonst(&p->q1.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q1.val,t))){
  989.             if(regavailable(1)){
  990.                 reg=get_reg(f,1,p);
  991.                 move(f,&p->q1,0,0,reg,t);
  992.                 p->q1.flags=REG|SCRATCH;p->q1.reg=reg;
  993.                 p->q1.val.vlong=l2zl(0L);
  994.             }
  995.         }
  996.         if((p->q2.flags&KONST)&&isquickkonst(&p->q2.val,t)&&((c!=ADD&&c!=SUB&&c!=ADDI2P&&c!=SUBIFP)||!isquickkonst2(&p->q2.val,t))){
  997.             if(regavailable(1)){
  998.                 reg=get_reg(f,1,p);
  999.                 move(f,&p->q2,0,0,reg,t);
  1000.                 p->q2.flags=REG|SCRATCH;p->q2.reg=reg;
  1001.                 p->q2.val.vlong=l2zl(0L);
  1002.             }
  1003.         }
  1004.  
  1005.     }
  1006.     return(p);
  1007. }
  1008. void pr(FILE *f,struct IC *p)
  1009. /*  Gibt Register frei, holt sie vom Stack                  */
  1010. {
  1011.     int i,size=0;
  1012.     /*  Haufen Gefummel um condition codes zu merken    */
  1013.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE)){
  1014.         char *fp;struct IC *branch;
  1015.         if(g_flags_val[1].l>=68000&&((p->typf&15)==FLOAT||(p->typf&15)==DOUBLE)) fp="f"; else fp="";
  1016.         branch=p;
  1017.         while(branch->code<BEQ||branch->code>=BRA) branch=branch->next;
  1018.         if((p->typf&UNSIGNED)||(p->typf&15)==POINTER){
  1019.             fprintf(f,"\ts%s\t-2(a7)\n",ubranch[branch->code-BEQ]+1);
  1020.         }else{
  1021.             fprintf(f,"\t%ss%s\t-2(a7)\n",fp,ename[branch->code]+1);
  1022.         }
  1023.         stored_cc=1;
  1024.     }
  1025.     for(i=MAXR;i>0;i--){
  1026.         if(regs[i]==2) regs[i]=0;
  1027.         if(regs[i]&4){
  1028.             regs[i]-=4;
  1029.             if(i<17) {fprintf(f,"\tmove.l\t(a7)+,%s\n",regnames[i]);stackoffset+=4;size+=4;}
  1030.              else {fprintf(f,"\tfmove.x\t(a7)+,%s\n",regnames[i]);stackoffset+=12;size+=12;}
  1031.         }
  1032.     }
  1033.     if((pushedreg&12)&&(p->code==TEST||p->code==COMPARE))
  1034.         fprintf(f,"\ttst.b\t-%d(a7)\n",size+2);
  1035. }
  1036.  
  1037. void probj(FILE *f,struct obj *p,int t,int verbose)
  1038. /*  Gibt Objekt auf Bildschirm aus                      */
  1039. {
  1040.     if(p->am){
  1041.     /*  Ausgabe der erweiterten Adressierungsarten  */
  1042.         if(!(c_flags_val[0].l&128)) {ierror(0);p->am=0;return;}
  1043.         if(p->am->skal>=0){
  1044.             long l=0;
  1045.             if(p->flags&D16OFF) l=zl2l(p->val.vlong);
  1046.             fprintf(f,"(%ld,%s",p->am->dist+l,regnames[p->am->basereg]);
  1047.             if(p->am->dreg){
  1048.                 fprintf(f,",%s",regnames[p->am->dreg&127]);
  1049.                 if(p->am->dreg&128) fprintf(f,".w"); else fprintf(f,".l");
  1050.                 if(p->am->skal) fprintf(f,"*%d",p->am->skal);
  1051.             }
  1052.             fprintf(f,")");
  1053.             return;
  1054.         }
  1055.         if((p->flags&D16OFF)&&!zleq(p->val.vlong)) ierror(0);
  1056.         if(p->am->skal==-1){
  1057.             fprintf(f,"(%s)+",regnames[p->am->basereg]);
  1058.             return;
  1059.         }
  1060.         if(p->am->skal==-2){    /*  Noch nicht implementiert    */
  1061.             fprintf(f,"-(%s)",regnames[p->am->basereg]);
  1062.             return;
  1063.         }
  1064.     }
  1065.     if(p->flags&DREFOBJ){
  1066.         fprintf(f,"(");
  1067.         if((p->flags&D16OFF)&&!zleq(p->val.vlong))
  1068.             {printval(f,&p->val,LONG,0);fprintf(f,",");}
  1069.     }
  1070.     if((p->flags&VARADR)&&!(verbose&2)) fprintf(f,"#");
  1071.     if(p->flags&VAR) {
  1072.         if(verbose&1){
  1073.             printval(f,&p->val,LONG,1);
  1074.             if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  1075.                 if(p->flags®)
  1076.                     fprintf(f,"+%s",regnames[p->reg]);
  1077.                 else
  1078.                     fprintf(f,"+%d(FP)", p->v->offset);
  1079.             }else{
  1080.                 if(p->v->storage_class==STATIC&&p->v->nesting>0){
  1081.                     fprintf(f,"+L%d",p->v->offset);
  1082.                 }else{
  1083.                     fprintf(f,"+_%s",p->v->identifier);
  1084.                 }
  1085.             }
  1086.             fprintf(f,"(%s)",p->v->identifier);
  1087.         }else{
  1088.             if(p->v->storage_class==AUTO||p->v->storage_class==REGISTER){
  1089.                 if(p->flags®){
  1090.                     fprintf(f,"%s",regnames[p->reg]);
  1091.                 }else{
  1092.                     long os;
  1093.                     os=zl2l(p->val.vlong);
  1094.                     if(c_flags_val[0].l&256){
  1095.                         if(p->v->offset<0) os=os+loff-p->v->offset;
  1096.                          else              os=os+p->v->offset;
  1097.                         fprintf(f,"(%ld+l%d,a7)",os-stackoffset,offlabel);
  1098.                     }else{
  1099.                         if(p->v->offset<0) os=os-p->v->offset+4;
  1100.                          else              os=os-(p->v->offset+szof(p->v->vtyp));
  1101.                         fprintf(f,"(%ld,a5)",os);
  1102.                     }
  1103.                 }
  1104.             }else{
  1105.                 if(!zleq(p->val.vlong)){printval(f,&p->val,LONG,0);fprintf(f,"+");}
  1106.                 if(p->v->storage_class==STATIC&&(p->v->vtyp->flags&15)!=FUNKT){
  1107.                     fprintf(f,"l%d",p->v->offset);
  1108.                 }else{
  1109.                     fprintf(f,"_%s",p->v->identifier);
  1110.                     if((g_flags[5]&USEDFLAG)&&!(p->flags&VARADR)&&(p->v->vtyp->flags&15)!=FUNKT)
  1111.                         fprintf(f,"(a4)");
  1112.                 }
  1113.             }
  1114.         }
  1115.     }
  1116.     if((p->flags®)&&!(p->flags&VAR)) fprintf(f,"%s",regnames[p->reg]);
  1117.     if(p->flags&KONST){
  1118.         /*  Das hier setzt voraus, dass Compiler Datentypen im  */
  1119.         /*  IEEE-Format nachbildet                              */
  1120.         if(t==FLOAT||t==DOUBLE){
  1121.             char str[10];int i;
  1122.             int *ip=(int *)&p->val.vfloat; /*   nicht schoen, aber...   */
  1123.             fprintf(f,"#$");sprintf(str,"%8x",*ip);
  1124.             for(i=0;i<8;i++) if(str[i]==' ') str[i]='0';
  1125.             fprintf(f,"%s",str);
  1126.             if(t==DOUBLE){
  1127.                 if(DEBUG&1) printf("doubleconst=%f\n",p->val.vdouble);
  1128.                 ip++;sprintf(str,"%8x",*ip);
  1129.                 for(i=0;i<10;i++) if(str[i]==' ') str[i]='0';
  1130.                 fprintf(f,"%s",str);
  1131.             }
  1132.         }else {fprintf(f,"#");printval(f,&p->val,t&31,verbose);}
  1133.     }
  1134.     if(p->flags&STACK) fprintf(f,"Stack");
  1135.     if(p->flags&DREFOBJ) fprintf(f,")");
  1136. }
  1137. char tsh[]={'w','l'};
  1138. int proflabel;
  1139. void function_top(FILE *f,struct Var *v,int offset)
  1140. /*  erzeugt Funktionskopf                       */
  1141. {
  1142.     if(g_flags_val[0].l!=68000) fprintf(f,"\tmachine\t%ld\n",g_flags_val[0].l);
  1143.     if(g_flags_val[1].l>68000) fprintf(f,"\tfpu\t1\n");
  1144.     if(g_flags[4]&USEDFLAG) fprintf(f,"\tnear\tcode\n");
  1145.     if(g_flags[5]&USEDFLAG) fprintf(f,"\tnear\ta4,-2\n");
  1146.     if(section!=CODE){fprintf(f,codename);section=CODE;}
  1147.     if(g_flags[6]&USEDFLAG){
  1148.         proflabel=++label;
  1149.         fprintf(f,"l%d\n\tdc.b\t\"%s\",0\n",proflabel,v->identifier);
  1150.     }
  1151.     if(v->storage_class==EXTERN) fprintf(f,"\tpublic\t_%s\n",v->identifier);
  1152.     fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  1153.     if(g_flags[6]&USEDFLAG)
  1154.         fprintf(f,"\tpea\tl%d\n\tpublic\t__startprof\n\tjsr\t__startprof\n\taddq.w\t#4,a7\n",proflabel);
  1155.     offset=-((offset+4-1)/4)*4;
  1156.     loff=-offset;offlabel=++label;
  1157.     if(c_flags_val[0].l&256){
  1158.         if(offset<0) fprintf(f,"\tsub%s.%s\t#%d,a7\n",quick[offset>=-8],strshort[offset>=-32768],-offset);
  1159.     }else{
  1160.         if(offset>=-32768||g_flags_val[0].l>=68020){
  1161.             fprintf(f,"\tlink.%c\ta5,#%d\n",tsh[offset<-32768],offset);
  1162.         }else{
  1163.             fprintf(f,"\tlink.w\ta5,#-32768\n");offset+=32768;
  1164.             fprintf(f,"\tsub.%c\t#%d,a5\n",tsh[offset<-32768],offset);
  1165.         }
  1166.     }
  1167.     if(g_flags_val[1].l>68000&&float_used) fprintf(f,"\tfmovem.x\tl%d,-(a7)\n",freglabel);
  1168.     fprintf(f,"\tmovem.l\tl%d,-(a7)\n",reglabel);
  1169.     /*  Was mach ich hier mit stackoffset?  */
  1170. }
  1171. void function_bottom(FILE *f,struct Var *v,int offset)
  1172. /*  erzeugt Funktionsende                       */
  1173. {
  1174.     int i,size=0;
  1175.     *reglist=0;
  1176.     for(i=1;i<=16;i++){
  1177.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  1178.             if(*reglist) strcat(reglist,"/");
  1179.             strcat(reglist,regnames[i]);size+=4;
  1180.         }
  1181.     }
  1182.     if(*reglist) fprintf(f,"l%d\treg\t%s\n\tmovem.l\t(a7)+,l%d\n",reglabel,reglist,reglabel);
  1183.         else fprintf(f,"l%d\treg\n",reglabel);
  1184.     *reglist=0;
  1185.     for(i=17;i<=MAXR;i++){
  1186.         if(regused[i]&&!regscratch[i]&&!regsa[i]){
  1187.             if(*reglist) strcat(reglist,"/");
  1188.             strcat(reglist,regnames[i]);size+=12;
  1189.         }
  1190.     }
  1191.     if(g_flags_val[1].l>68000&&float_used){
  1192.         if(*reglist) fprintf(f,"l%d\tfreg\t%s\n\tfmovem.x\t(a7)+,l%d\n",freglabel,reglist,freglabel);
  1193.             else fprintf(f,"l%d\tfreg\n",freglabel);
  1194.     }
  1195.     if(c_flags_val[0].l&256){
  1196.         if(loff) fprintf(f,"\tadd%s.%s\t#%ld,a7\n",quick[loff<=8],strshort[loff<32768],loff);
  1197.         fprintf(f,"l%d\tEQU\t%d\n",offlabel,size);
  1198.     }else fprintf(f,"\tunlk\ta5\n");
  1199.     if(g_flags[6]&USEDFLAG)
  1200.         fprintf(f,"\tpea\tl%d\n\tpublic\t__endprof\n\tjsr\t__endprof\n\taddq.w\t#4,a7\n",proflabel);
  1201.     fprintf(f,"\trts\n");
  1202. }
  1203. void gen_ds(FILE *f,int size,struct Typ *t)
  1204. /*  generiert Speicher fuer size Bytes mit Null initialisiert.  */
  1205. /*  Aufpassen, dass kein BSS in einem teilweise initialisierten */
  1206. /*  Array erzeugt wird.                                         */
  1207. /*  t darf 0 sein, dann sind es nur Fuellbytes                  */
  1208. {
  1209.     if(section!=BSS&&newobj){fprintf(f,bssname);section=BSS;}
  1210.     fprintf(f,"\tds.b\t%d\n",size);newobj=0;
  1211. }
  1212. void gen_align(FILE *f,int align)
  1213. /*  generiert alignment auf align Bytes (oder aehnlich)         */
  1214. {
  1215.     if(align>1) fprintf(f,"\tcnop\t0,4\n");
  1216. }
  1217. void gen_var_head(FILE *f,struct Var *v)
  1218. /*  generiert Kopf fuer eine Variable                           */
  1219. {
  1220.     if(v->storage_class==STATIC){
  1221.         if((v->vtyp->flags&15)==FUNKT) return;
  1222.         if(v->clist&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1223.         if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1224.         fprintf(f,"\tcnop\t0,4\nl%d\n",v->offset);
  1225.         newobj=1;
  1226.     }
  1227.     if(v->storage_class==EXTERN){
  1228.         fprintf(f,"\tpublic\t_%s\n",v->identifier);
  1229.         if(v->flags&(DEFINED|TENTATIVE)){
  1230.             if(v->clist&§ion!=DATA){fprintf(f,dataname);section=DATA;}
  1231.             if(!v->clist&§ion!=BSS){fprintf(f,bssname);section=BSS;}
  1232.             fprintf(f,"\tcnop\t0,4\n_%s\n",v->identifier);
  1233.             newobj=1;
  1234.         }
  1235.     }
  1236. }
  1237. void gen_dc(FILE *f,int t,struct const_list *p)
  1238. /*  generiert Konstanten fuer Typ t aus clist p                 */
  1239. {
  1240.     char s;
  1241.     if(!p){ierror(0);return;}
  1242.     if(section!=DATA){fprintf(f,dataname);section=DATA;}
  1243.     if((t&15)==FLOAT||(t&15)==DOUBLE) s='l'; else s=x_t[t&15];
  1244.     fprintf(f,"\tdc.%c\t",s);
  1245.     if(!p->tree){
  1246.         if((t&15)==FLOAT||(t&15)==DOUBLE){
  1247.         /*  auch wieder nicht sehr schoen und IEEE noetig   */
  1248.             int *ip;
  1249.             ip=(int *)&p->val.vdouble;
  1250.             fprintf(f,"$%x",*ip);
  1251.             if((t&15)==DOUBLE) fprintf(f,",$%x",*(++ip));
  1252.         }else{
  1253.             printval(f,&p->val,t&31,0);
  1254.         }
  1255.     }else{
  1256.         p->tree->o.am=0;
  1257.         probj(f,&p->tree->o,t&31,2);
  1258.     }
  1259.     fprintf(f,"\n");newobj=0;
  1260. }
  1261.  
  1262. void move(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1263. /*  erzeugt eine move Anweisung...Da sollen mal Optimierungen rein  */
  1264. {
  1265.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1266.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  1267.     if(zreg==qreg&&zreg) return;
  1268.     if(q&&(q->flags&VARADR)&&zreg>=1&&zreg<=8){
  1269.         fprintf(f,"\tlea\t");
  1270.         q->flags&=~VARADR;probj(f,q,t,0);q->flags|=VARADR;
  1271.         fprintf(f,",%s\n",regnames[zreg]);
  1272.         return;
  1273.     }
  1274.     if(zreg>=9&&zreg<=16&&q&&(q->flags&KONST)&&isquickkonst(&q->val,t)){
  1275.         fprintf(f,"\tmoveq\t");
  1276.     }else{
  1277.         if(zreg>=17||qreg>=17){
  1278.             if(qreg>=17&&zreg>=17) fprintf(f,"\tfmove.x\t");
  1279.              else fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  1280.         }else{
  1281.             fprintf(f,"\tmove.%c\t",x_s[sizetab[t&15]]);
  1282.         }
  1283.     }
  1284.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1285.     fprintf(f,",");
  1286.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1287.     fprintf(f,"\n");
  1288. }
  1289. void add(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1290. /*  erzeugt eine add Anweisung...Da sollen mal Optimierungen rein   */
  1291. {
  1292.     if(!qreg&&!q) ierror(0);
  1293.     if(!zreg&&!z) ierror(0);
  1294.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1295.     if(!qreg&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  1296.         fprintf(f,"\taddq.%c\t",x_t[t&15]);
  1297.     }else{
  1298.         /*  hier noch Abfrage, ob #c.w,ax   */
  1299.         fprintf(f,"\tadd.%c\t",x_t[t&15]);
  1300.     }
  1301.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1302.     fprintf(f,",");
  1303.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1304.     fprintf(f,"\n");
  1305. }
  1306. void sub(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg,int t)
  1307. /*  erzeugt eine sub Anweisung...Da sollen mal Optimierungen rein   */
  1308. {
  1309.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1310.     if(q&&(q->flags&KONST)&&isquickkonst2(&q->val,t)){
  1311.         fprintf(f,"\tsubq.%c\t",x_t[t&15]);
  1312.     }else{
  1313.         /*  hier noch Abfrage, ob #c.w,ax   */
  1314.         fprintf(f,"\tsub.%c\t",x_t[t&15]);
  1315.     }
  1316.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1317.     fprintf(f,",");
  1318.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1319.     fprintf(f,"\n");
  1320. }
  1321. void mult(FILE *f,struct obj *q,int qreg,struct obj *z,int zreg, int t,int c,struct IC *p)
  1322. /*  erzeugt eine mult Anweisung...Da sollen mal Optimierungen rein  */
  1323. /*  erzeugt auch div/mod etc.                                       */
  1324. {
  1325.     int modreg;
  1326.     if(!qreg&&(q->flags&(REG|DREFOBJ))==REG) qreg=q->reg;
  1327.     if(!zreg&&(z->flags&(REG|DREFOBJ))==REG) zreg=z->reg;
  1328.     if((c==MULT||c==DIV||c==MOD)&&g_flags_val[0].l<68020&&sizetab[t&15]==4){
  1329.         if(c==MULT){
  1330.         /*  ist das mit get_reg(.,.,0) ok? nochmal ueberdenken...   */
  1331.         /*  ...die ganze Routine am besten...                       */
  1332.         /*  ...es war nicht, deshalb ist es jetzt geaendert         */
  1333.             int dx,dy,t1,t2;
  1334.             if(zreg>=9&&zreg<=16){
  1335.                 dx=zreg;
  1336.             }else{
  1337.                 dx=get_reg(f,1,p);
  1338.                 move(f,z,0,0,dx,t);
  1339.             }
  1340.             if(qreg>=9&&qreg<=16&&qreg!=dx){
  1341.                 dy=qreg;
  1342.             }else{
  1343.                 dy=get_reg(f,1,p);
  1344.                 move(f,q,0,0,dy,t);
  1345.             }
  1346.             t1=get_reg(f,1,p);t2=get_reg(f,1,p);
  1347.             if(t1==dx||t2==dx||t1==dy||t2==dy) ierror(0);
  1348.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dx],regnames[t1]);
  1349.             fprintf(f,"\tmove.l\t%s,%s\n",regnames[dy],regnames[t2]);
  1350.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  1351.             fprintf(f,"\tswap\t%s\n",regnames[t2]);
  1352.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[t1]);
  1353.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dx],regnames[t2]);
  1354.             fprintf(f,"\tmulu.w\t%s,%s\n",regnames[dy],regnames[dx]);
  1355.             fprintf(f,"\tadd.w\t%s,%s\n",regnames[t2],regnames[t1]);
  1356.             fprintf(f,"\tswap\t%s\n",regnames[t1]);
  1357.             fprintf(f,"\tclr.w\t%s\n",regnames[t1]);
  1358.             fprintf(f,"\tadd.l\t%s,%s\n",regnames[t1],regnames[dx]);
  1359.             if(zreg!=dx) move(f,0,t1,z,0,t);
  1360.         }else ierror(0);
  1361.         return;
  1362.     }
  1363.     if(c==MULT){
  1364.         /*  das duerfte nur der Aesthetik dienen... */
  1365.         if(t&UNSIGNED) fprintf(f,"\tmulu.%c\t",x_t[t&15]); else fprintf(f,"\tmuls.%c\t",x_t[t&15]);
  1366.     }
  1367.     if(c==DIV){
  1368.         if(t&UNSIGNED) fprintf(f,"\tdivu.%c\t",x_t[t&15]); else fprintf(f,"\tdivs.%c\t",x_t[t&15]);
  1369.     }
  1370.     if(c==MOD){
  1371.         /*  das hier ist nicht besonders toll geloest   */
  1372.         modreg=get_reg(f,1,p);
  1373.         if(t&UNSIGNED) fprintf(f,"\tdivul.%c\t",x_t[t&15]); else fprintf(f,"\tdivsl.%c\t",x_t[t&15]);
  1374.         if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1375.         fprintf(f,",%s:%s\n",regnames[modreg],regnames[zreg]);
  1376.         fprintf(f,"\tmove.l\t%s,%s\n",regnames[modreg],regnames[zreg]);
  1377.         return;
  1378.     }
  1379.     if(qreg) fprintf(f,"%s",regnames[qreg]); else probj(f,q,t,0);
  1380.     fprintf(f,",");
  1381.     /*  eigentlich muss zreg!=0 sein...     */
  1382.     if(zreg) fprintf(f,"%s",regnames[zreg]); else probj(f,z,t,0);
  1383.     fprintf(f,"\n");
  1384. }
  1385. void saverestoreregs(FILE *f,int c,int dontsave)
  1386. {
  1387.     int i,s,e,size=0;static char fp[4]="\0\0\0";
  1388.     if(c==SAVEREGS){s=17;e=MAXR;} else {s=1;e=16;}
  1389.     while(1){
  1390.         *reglist=0;
  1391.         for(i=s;i<=e;i++){
  1392.             if(regs[i]==1&®scratch[i]&&i!=dontsave){
  1393.                 if(*reglist) strcat(reglist,"/");
  1394.                 strcat(reglist,regnames[i]);
  1395.                 if(i<17) size+=4; else size+=12;
  1396.             }
  1397.         }
  1398.         if(*reglist){
  1399.             char s;
  1400.             if(e==MAXR) {*fp='f';s='x';} else {*fp=0;s='l';}
  1401.             if(c==SAVEREGS) fprintf(f,"\t%smovem.%c\t%s,-(a7)\n",fp,s,reglist);
  1402.              else fprintf(f,"\t%smovem.%c\t(a7)+,%s\n",fp,s,reglist);
  1403.         }
  1404.         if((s==17&&c==RESTOREREGS)||(s==1&&c==SAVEREGS)) break;
  1405.         if(s==17){s=1;e=16;} else {s=17;e=MAXR;}
  1406.     }
  1407.     if(c==SAVEREGS) stackoffset-=size; else stackoffset+=size;
  1408. }
  1409. struct IC *am_freedreg[9],*am_shiftdreg[9];
  1410. struct IC *am_dist_ic[9],*am_dreg_ic[9],*am_use[9];
  1411. /*  am_dist_ic und am_dreg_ic werden auch fuer (ax)+ benutzt    */
  1412. long am_dist[9],am_dreg[9],am_base[9],am_inc[9],am_skal[9],am_dbase[9];
  1413. #define AMS sizeof(struct AddressingMode)
  1414.  
  1415. void clear_am(int reg)
  1416. /*  loescht Werte fuer erweiterte Adressierungsarten fuer Register reg  */
  1417. {
  1418.     if(DEBUG&32) printf("clear_am(%s)\n",regnames[reg]);
  1419.     if(reg<=8){
  1420.         am_dist_ic[reg]=am_dreg_ic[reg]=am_use[reg]=0;
  1421.         am_dist[reg]=am_dreg[reg]=am_base[reg]=am_inc[reg]=0;
  1422.     }else{
  1423.         reg-=8;
  1424.         am_freedreg[reg]=am_shiftdreg[reg]=0;
  1425.         am_skal[reg]=am_dbase[reg]=0;
  1426.     }
  1427. }
  1428. int addressing(void)
  1429. /*  Untersucht ICs auf erweiterte Addresierungsarten    */
  1430. {
  1431.     struct IC *p;int count,localused=0;
  1432.     if(DEBUG&32) printf("addressing() started\n");
  1433.     for(count=1;count<=16;count++) clear_am(count);
  1434.     for(count=0,p=first_ic;p;p=p->next){
  1435.         int c=p->code,q1reg=p->q1.reg,q2reg=p->q2.reg,zreg=p->z.reg;
  1436.         if(c==ADDI2P) c=ADD;
  1437.         if(c==SUBIFP) c=SUB;
  1438.         if(DEBUG&32) pric2(stdout,p);
  1439.         if(!localused){
  1440.             if((p->q1.flags&(VAR|REG))==VAR&&(p->q1.v->storage_class==AUTO||p->q1.v->storage_class==REGISTER)&&p->q1.v->offset>=0)
  1441.                 localused=1;
  1442.             if((p->q2.flags&(VAR|REG))==VAR&&(p->q2.v->storage_class==AUTO||p->q2.v->storage_class==REGISTER)&&p->q2.v->offset>=0)
  1443.                 localused=1;
  1444.             if((p->z.flags&(VAR|REG))==VAR&&(p->z.v->storage_class==AUTO||p->z.v->storage_class==REGISTER)&&p->z.v->offset>=0)
  1445.                 localused=1;
  1446.             if(DEBUG&32&&localused==1) printf("localused=1\n");
  1447.         }
  1448.         if(c==ASSIGN&&isreg(q1)&&isreg(z)&&q1reg>=1&&q1reg<=8&&zreg>=1&&zreg<=8){
  1449.         /*  fuer (ax)+  */
  1450.             int i;
  1451.             for(i=1;i<=8;i++)
  1452.                 if(am_base[i]==zreg||am_base[i]==q1reg) clear_am(i);
  1453.             clear_am(zreg);am_base[zreg]=q1reg;am_dreg_ic[zreg]=p;
  1454.             if(DEBUG&32) printf("move %s,%s found\n",regnames[q1reg],regnames[zreg]);
  1455.             continue;
  1456.         }
  1457.         if(c==MULT&&g_flags_val[0].l>=68020&&(p->q2.flags&KONST)&&isreg(z)&&zreg>=9&&zreg<=16){
  1458.         /*  dx=a*const, fuer Skalierung    */
  1459.             int dreg=zreg-8;
  1460.             if(DEBUG&32) printf("mult x,const->dreg found\n");
  1461.             if(am_skal[dreg]) {clear_am(zreg);continue;}
  1462.             eval_const(&p->q2.val,p->typf&31);
  1463.             am_skal[dreg]=zl2l(vlong);
  1464.             if(am_skal[dreg]!=2&&am_skal[dreg]!=4&&am_skal[dreg]!=8)
  1465.                 {clear_am(zreg);continue;}
  1466.             am_shiftdreg[dreg]=p;
  1467.             if(isreg(q1)&&q1reg>=9&&q1reg<=16) am_dbase[dreg]=q1reg; else am_dbase[dreg]=zreg;
  1468.             if(DEBUG&32) printf("is usable\n");
  1469.             continue;
  1470.         }
  1471.         if((c==ADD||c==SUB)&&(p->q2.flags&KONST)&&zreg>=1&&zreg<=8&&isreg(z)){
  1472.         /*  add ax,#const,ax->az Test auf d8/16 fehlt noch    */
  1473.             long l;
  1474.             if(am_dist[zreg]||am_inc[zreg]) {clear_am(zreg);continue;} /* nur ein Offset */
  1475.             eval_const(&p->q2.val,p->typf&31);
  1476.             l=zl2l(vlong);
  1477.             if(c==SUB) l=-l;
  1478.             if(isreg(q1)&&q1reg==zreg&&(l==1||l==2||l==4)){
  1479.             /*  ax+=const, fuer (ax)+   */
  1480.                 int i,f;
  1481.                 for(f=0,i=1;i<=8;i++){
  1482.                     if(am_base[i]==zreg&&!am_dreg[i]&&!am_dist[i]){
  1483.                         if(f) ierror(0);
  1484.                         am_inc[i]=l;am_dist_ic[i]=p;f=i;
  1485.                         if(DEBUG&32) printf("inc %s found\n",regnames[i]);
  1486.                     }
  1487.                 }
  1488.                 if(f) continue;
  1489.             }
  1490.             am_dist[zreg]=l;
  1491.             if(DEBUG&32) printf("dist=%ld\n",am_dist[zreg]);
  1492.             if(g_flags_val[0].l<68020){
  1493.             /*  bei <68020 darf der Offset nur 16bit oder 8bit bei dreg sein */
  1494.                 if((am_dreg[zreg]&&(am_dist[zreg]<-128||am_dist[zreg]>127))||am_dist[zreg]<-32768||am_dist[zreg]>32767)
  1495.                     {clear_am(zreg);continue;}
  1496.             }
  1497.             am_dist_ic[zreg]=p;
  1498.             if(am_base[zreg]){
  1499.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  1500.             }else{
  1501.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  1502.             }
  1503.             if(DEBUG&32) printf("add #const,%s found\n",regnames[zreg]);
  1504.             continue;
  1505.         }
  1506.         if(c==ADD&&q2reg>=9&&q2reg<=16&&isreg(q2)&&zreg>=1&&zreg<=8&&isreg(z)){
  1507.         /*  add ax,dy->az   */
  1508.             if(am_dreg[zreg]||am_inc[zreg]) {clear_am(zreg);continue;} /* nur ein Regoffset */
  1509.             if(g_flags_val[0].l<68020&&(am_dist[zreg]<-128||am_dist[zreg]>127))
  1510.                 {clear_am(zreg);continue;} /* bei <68020 nur 8bit Offset */
  1511.             am_dreg[zreg]=q2reg;
  1512.             if((p->typf&15)==SHORT) am_dreg[zreg]|=128; /* dx.w statt dx.l */
  1513.             am_dreg_ic[zreg]=p;
  1514.             if(am_base[zreg]){
  1515.                 if(q1reg!=zreg||!isreg(q1)) {clear_am(zreg);continue;}
  1516.             }else{
  1517.                 if(q1reg>=1&&q1reg<=8&&isreg(q1)) am_base[zreg]=q1reg; else am_base[zreg]=zreg;
  1518.             }
  1519.             if(DEBUG&32) printf("add %s,%s found\n",regnames[q2reg],regnames[zreg]);
  1520.             continue;
  1521.         }
  1522.         if(c==FREEREG){
  1523.         /*  wir koennen den Modus tatsaechlich benutzen */
  1524.             struct AddressingMode *am;struct IC *p1,*p2;int dreg;
  1525.             if(DEBUG&32) printf("freereg found, code=%d\n",p->code);
  1526.             if(q1reg>=9&&q1reg<=16) {am_freedreg[q1reg-8]=p;if(DEBUG&32) printf("freedreg[%d]=%lx\n",q1reg-8,(long)p);}
  1527.             if(q1reg>8||!am_use[q1reg]) continue;
  1528.             if(DEBUG&32) printf("could really use %s\n",regnames[q1reg]);
  1529.             p1=am_dist_ic[q1reg];p2=am_dreg_ic[q1reg];
  1530.             if(am_base[q1reg]==q1reg){
  1531.                 if(p1) {p1->q2.flags=0;p1->code=ASSIGN;p1->q2.reg=4;p1->typf=POINTER;}
  1532.                 if(p2) {p2->q2.flags=0;p2->code=ASSIGN;p2->q2.reg=4;p2->typf=POINTER;}
  1533.             }else{
  1534.                 if(p1) remove_IC(p1);
  1535.                 if(p2) remove_IC(p2);
  1536.             }
  1537.             dreg=(am_dreg[q1reg]&127)-8;
  1538.             am=(struct AddressingMode *)mymalloc(AMS);
  1539.             am->skal=0;
  1540.             am->basereg=am_base[q1reg];
  1541.             am->dist=am_dist[q1reg];
  1542.             am->dreg=am_dreg[q1reg];
  1543.             if(am_inc[q1reg]) am->skal=-1;
  1544.             if(dreg>0){
  1545.                 /*  bei (d,ax,dy) das freereg dy nach hinten verschieben    */
  1546.                 if(p1=am_freedreg[dreg]){
  1547.                     if(DEBUG&32) printf("freereg %s moved from %lx to %lx\n",regnames[dreg+8],(long)p1,(long)p);
  1548.                     if(p1->code!=FREEREG){ierror(0);printf("freereg[%d]=%lx\n",dreg,(long)p1);continue;}
  1549.                     if(!p1->next) {ierror(0);continue;}
  1550.                     if(!p1->prev) {ierror(0);continue;}
  1551.                     p1->prev->next=p1->next;
  1552.                     p1->next->prev=p1->prev;
  1553.                     p1->next=p->next;
  1554.                     p1->prev=p;
  1555.                     if(p->next) p->next->prev=p1;
  1556.                     p->next=p1;
  1557.                 }
  1558.                 if(am_skal[dreg]){
  1559.                 /*  Skalierung bearbeiten   */
  1560.                     am->skal=am_skal[dreg];
  1561.                     am->dreg=am_dbase[dreg];
  1562.                     p1=am_shiftdreg[dreg];
  1563.                     if(am_dbase[dreg]==dreg+8){
  1564.                         p1->code=ASSIGN;p1->q2.flags=0;p1->q2.reg=sizetab[p1->typf&15];
  1565.                     }else remove_IC(p1);
  1566.                     clear_am(dreg+8);
  1567.                 }
  1568.             }
  1569.             /*  das hier duerfte unnoetig sein, da die Adressierungsart in  */
  1570.             /*  einem IC eigentlich hoechstens einmal vorkommen darf        */
  1571.             p1=am_use[q1reg];
  1572.             if(p1->q1.reg==q1reg&&((p1->q1.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1573.                 p1->q1.am=(struct AddressingMode *)mymalloc(AMS);
  1574.                 memcpy(p1->q1.am,am,AMS);
  1575.                 if(DEBUG&32) printf("q1 patched\n");
  1576.             }
  1577.             if(p1->q2.reg==q1reg&&((p1->q2.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1578.                 p1->q2.am=(struct AddressingMode *)mymalloc(AMS);
  1579.                 memcpy(p1->q2.am,am,AMS);
  1580.                 if(DEBUG&32) printf("q2 patched\n");
  1581.             }
  1582.             if(p1->z.reg==q1reg&&((p1->z.flags&(DREFOBJ|REG))==(DREFOBJ|REG))){
  1583.                 p1->z.am=(struct AddressingMode *)mymalloc(AMS);
  1584.                 memcpy(p1->z.am,am,AMS);
  1585.                 if(DEBUG&32) printf("z patched\n");
  1586.             }
  1587.             free(am);c++;
  1588.             clear_am(q1reg);
  1589.             continue;
  1590.         }
  1591.         if(c==LABEL){
  1592.             int i;      /*  ueber Labels hinweg ist das zu unsicher */
  1593.             for(i=1;i<=16;i++) clear_am(i);
  1594.             continue;
  1595.         }
  1596.         if(((p->q1.flags&(DREFOBJ|REG))&&q1reg<=8&&(am_inc[q1reg]||am_dist[q1reg]||am_dreg[q1reg]))){
  1597.             if(am_use[q1reg]) clear_am(q1reg); else am_use[q1reg]=p;
  1598.             if(am_inc[q1reg]&&am_inc[q1reg]!=sizetab[p->typf&15]) clear_am(q1reg);
  1599.             if(DEBUG&32) printf("use of %s found\n",regnames[q1reg]);
  1600.         }
  1601.         if(((p->q2.flags&(DREFOBJ|REG))&&q2reg<=8&&(am_inc[q2reg]||am_dist[q2reg]||am_dreg[q2reg]))){
  1602.             if(am_use[q2reg]) clear_am(q2reg); else am_use[q2reg]=p;
  1603.             if(am_inc[q2reg]&&am_inc[q2reg]!=sizetab[p->typf&15]) clear_am(q2reg);
  1604.             if(DEBUG&32) printf("use of %s found\n",regnames[q2reg]);
  1605.         }
  1606.         if(((p->z.flags&(DREFOBJ|REG))&&zreg<=8&&(am_inc[zreg]||am_dist[zreg]||am_dreg[zreg]))){
  1607.             if(am_use[zreg]) clear_am(zreg); else am_use[zreg]=p;
  1608.             if(am_inc[zreg]&&am_inc[zreg]!=sizetab[p->typf&15]) clear_am(zreg);
  1609.             if(DEBUG&32) printf("use of %s found\n",regnames[zreg]);
  1610.         }
  1611.         if(c==ALLOCREG){
  1612.         /*  allocreg zaehlt als zerstoerung von reg */
  1613.             p->z.flags=REG;
  1614.             p->z.reg=zreg=q1reg;
  1615.         }
  1616.         if(q1reg>=1&&q1reg<=16&&isreg(q1)) clear_am(q1reg);
  1617.         if(q2reg>=1&&q2reg<=16&&isreg(q2)) clear_am(q2reg);
  1618.         if(zreg>=1&&zreg<=16&&isreg(z)) clear_am(zreg);
  1619.         if(isreg(z)&&zreg<=16){
  1620.         /*  schauen, ob eines der Register ueberschrieben wird  */
  1621.         /*  wohl noch sehr langsam                              */
  1622.             int i;
  1623.             for(i=1;i<=8;i++)
  1624.                 if(!am_use[i]&&(am_base[i]==zreg||(am_dreg[i]&127)==zreg)) clear_am(i);
  1625.         }
  1626.         if(c==ALLOCREG) p->z.flags=0;
  1627.     }
  1628.     if(DEBUG&1) printf("%d adderessingmodes used, localused=%d\n",count,localused);
  1629.     return(localused);
  1630. }
  1631. int alignment(struct obj *o)
  1632. /*  versucht rauszufinden, wie ein Objekt alignet ist   */
  1633. {
  1634.     /*  wenn es keine Variable ist, kann man nichts aussagen    */
  1635.     long os;
  1636.     if((o->flags&(DREFOBJ|VAR))!=VAR||o->am) return(0);
  1637.     if(!o->v) ierror(0);
  1638.     os=zl2l(o->val.vlong);
  1639.     if(o->v->storage_class==AUTO||o->v->storage_class==REGISTER){
  1640.         if(c_flags_val[0].l&256){
  1641.             if(o->v->offset<0) os=os+loff-o->v->offset;
  1642.              else              os=os+o->v->offset;
  1643.         }else{
  1644.             if(o->v->offset<0) os=os-o->v->offset+4;
  1645.              else              os=os-(o->v->offset+szof(o->v->vtyp));
  1646.         }
  1647.     }
  1648.     return(os&3);
  1649. }
  1650. void assign(FILE *f,struct IC *p,struct obj *q,struct obj *z,int c,int size,int t)
  1651. /*  Generiert Code fuer Zuweisungen und PUSH/POP; hier noch einiges zu tun  */
  1652. {
  1653.     /*  auch noch sehr fpu-spezifisch   */
  1654.     if(t==FLOAT||t==DOUBLE){
  1655.         if(q&&(q->flags&KONST)){
  1656.             if(z&&(z->flags&(DREFOBJ|REG))==REG){
  1657.             /*  FP-Konstante->Register (muss immer reinpassen)  */
  1658.                 if(z->reg>=17) fprintf(f,"\tfmove"); else fprintf(f,"\tmove");
  1659.                 fprintf(f,".%c\t",x_t[t&15]);probj(f,q,t,0);
  1660.                 fprintf(f,",%s\n",regnames[z->reg]);
  1661.             }else{
  1662.             /*  FP-Konstante->Speicher (evtl. auf zweimal)  */
  1663.                 int m,*ip=(int *)&q->val.vfloat; /* nicht sehr schoen  */
  1664.                 if(c==PUSH&&t==DOUBLE) {fprintf(f,"\tmove.l\t#$%x,-(a7)\n",ip[1]);stackoffset-=4;}
  1665.                 fprintf(f,"\tmove.l\t#$%x,",*ip);
  1666.                 if(c==ASSIGN) probj(f,z,t,0); else {fprintf(f,"-(a7)");stackoffset-=4;}
  1667.                 fprintf(f,"\n");
  1668.                 if(t!=DOUBLE||c==PUSH) return;
  1669.                 ip++;m=0;
  1670.                 if(z&&z->flags®){
  1671.                     m=1;z->flags|=D16OFF;
  1672.                     z->val.vlong=l2zl(0L);
  1673.                 }
  1674.                 vlong=l2zl(4L);
  1675.                 z->val.vlong=zladd(z->val.vlong,vlong);
  1676.                 fprintf(f,"\tmove.l\t#$%x,",*ip);probj(f,z,t,0);
  1677.                 fprintf(f,"\n");
  1678.                 if(m){
  1679.                     z->flags&=~D16OFF;vlong=l2zl(4L);
  1680.                     z->val.vlong=zlsub(z->val.vlong,vlong);
  1681.                 }
  1682.             }
  1683.             return;
  1684.         }
  1685.         if((q&&(q->flags®)&&q->reg>=17)||(z&&(z->flags®)&&z->reg>=17)){
  1686.             if(c==ASSIGN&&q->reg==z->reg) return;
  1687.             fprintf(f,"\tfmove.%c\t",x_t[t&15]);
  1688.             if(c==POP) {fprintf(f,"(a7)+");stackoffset+=size;} else probj(f,q,t,0);
  1689.             fprintf(f,",");
  1690.             if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj(f,z,t,0);
  1691.             fprintf(f,"\n");return;
  1692.         }
  1693.     }
  1694.     if(size<=4&&(t&15)!=ARRAY){
  1695.         if((t&15)==STRUCT||(t&15)==UNION){
  1696.             if(size==2) t=SHORT; else t=LONG;
  1697.         }
  1698.         if(c==ASSIGN){move(f,q,0,z,0,t);return;}
  1699.         /*  Sonderfall pea  */
  1700.         if((q->flags&VARADR)&&c==PUSH){
  1701.             fprintf(f,"\tpea\t");
  1702.             q->flags&=~VARADR; probj(f,q,t,0); q->flags|=VARADR;
  1703.             fprintf(f,"\n"); stackoffset-=4;return;
  1704.         }
  1705.         fprintf(f,"\tmove.%c\t",x_s[size]);
  1706.         if(c==POP) {fprintf(f,"(a7)+");stackoffset+=size;} else probj(f,q,t,0);
  1707.         fprintf(f,",");
  1708.         if(c==PUSH) {fprintf(f,"-(a7)");stackoffset-=size;} else probj(f,z,t,0);
  1709.         fprintf(f,"\n");return;
  1710.     }else{
  1711.         int a1,a2,qreg,zreg,dreg,s=size,loops;char *cpstr;
  1712.         if(c==PUSH) cpstr="\tmove.%c\t-(%s),-(%s)\n"; else cpstr="\tmove.%c\t(%s)+,(%s)+\n";
  1713.         if(c==POP){
  1714.             qreg=8;
  1715.         }else{
  1716.             if(q->flags==(SCRATCH|REG|DREFOBJ)&&q->reg>=1&&q->reg<=8&&!q->am){
  1717.                 qreg=q->reg;
  1718.             }else{
  1719.                 if(c!=ASSIGN&&!regavailable(0)) printf("WARNING: PUSH PROBLEM(1)!\n");
  1720.                 qreg=get_reg(f,0,p);
  1721.                 fprintf(f,"\tlea\t");probj(f,q,POINTER,0);
  1722.                 fprintf(f,",%s\n",regnames[qreg]);
  1723.             }
  1724.         }
  1725.         if(c==PUSH){
  1726.             zreg=8;
  1727.             fprintf(f,"\tadd%s.%s\t#%d,%s\n",quick[s<=8],strshort[s<=32767],s,regnames[qreg]);
  1728.         }else{
  1729.             zreg=get_reg(f,0,p);
  1730.             fprintf(f,"\tlea\t");probj(f,z,POINTER,0);
  1731.             fprintf(f,",%s\n",regnames[zreg]);
  1732.         }
  1733.         if(c!=POP) a1=alignment(q); else a1=0;
  1734.         if(c!=PUSH)  a2=alignment(z); else a2=0;
  1735.         if((a1&1)&&(a2&1)){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;a1&=~1;a2&=~1;}
  1736.         if((a1&2)&&(a2&2)){fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);s-=2;a1&=~2;a2&=~2;}
  1737.         if(!(a1&1)&&!(a2&1)) loops=s/16-1; else loops=s/4-1;
  1738.         if(loops>0){
  1739.             if(c!=ASSIGN&&!regavailable(1)) printf("WARNING: PUSH PROBLEM(2)!\n");
  1740.             dreg=get_reg(f,1,p);
  1741.             fprintf(f,"\tmove%s.l\t#%d,%s\nl%d\n",quick[loops>=-128&&loops<=127],loops,regnames[dreg],++label);
  1742.         }
  1743.         if(loops>=0){
  1744.             int t;
  1745.             if(!(a1&1)&&!(a2&1)) t='l'; else t='b';
  1746.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1747.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1748.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1749.             fprintf(f,cpstr,t,regnames[qreg],regnames[zreg]);
  1750.         }
  1751.         if(loops>0) fprintf(f,"\tdbra\t%s,l%d\n",regnames[dreg],label);
  1752.         if(!(a1&1)&&!(a2&1)){
  1753.             if(s&8){
  1754.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1755.                 fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1756.             }
  1757.             if(s&4) fprintf(f,cpstr,'l',regnames[qreg],regnames[zreg]);
  1758.             if(s&2) fprintf(f,cpstr,'w',regnames[qreg],regnames[zreg]);
  1759.             if(s&1) fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);
  1760.         }else{
  1761.             s&=3;
  1762.             while(s){fprintf(f,cpstr,'b',regnames[qreg],regnames[zreg]);s--;}
  1763.         }
  1764.         if(c==PUSH) stackoffset-=size;
  1765.         if(c==POP)  stackoffset+=size;
  1766.     }
  1767.     return;
  1768. }
  1769.  
  1770. int must_convert(np p,int t)
  1771. /*  liefert 1, wenn fuer Umwandlung von p->o nach Typ t tatsaechlich    */
  1772. /*  Code erzeugt werden muss, sonst 0                                   */
  1773. {
  1774.     int o=p->ntyp->flags,op=o&15,tp=t&15;
  1775.     /*  signed und unsigned integers der selben Groesse sind gleich */
  1776.     if((t&UNSIGNED)&&(o&UNSIGNED)&&(sizetab[tp]==sizetab[op])) return(0);
  1777.     /*  int==long   */
  1778.     if((tp==INT&&op==LONG)||(tp==LONG&&op==INT)) return(0);
  1779.     /*  float und double gibt es in fp-Registern nicht  */
  1780.     if((tp==FLOAT||tp==DOUBLE)&&(op==FLOAT||op==DOUBLE)&&(p->o.flags®)&&p->o.reg>=17&&p->o.reg<=24)
  1781.         return(0);
  1782.  
  1783.     return(1);
  1784. }
  1785.  
  1786.